diff --git a/extras/conf/Includes/Game_SRB222.cfg b/extras/conf/Includes/Game_SRB222.cfg new file mode 100644 index 000000000..3c4b11e9f --- /dev/null +++ b/extras/conf/Includes/Game_SRB222.cfg @@ -0,0 +1,77 @@ +// Default lump name for new map +defaultlumpname = "MAP01"; +//GZDB specific. Don't try to load lumps that don't exist. +basegame = 0; + +//Sky textures for vanilla maps +defaultskytextures +{ + SKY1 = "MAP01,MAP02,MAP03,MAP33,MAP50,MAP60,MAPF0,MAPM0"; + SKY2 = "MAPM7,MAPMB"; + SKY4 = "MAP04,MAP06,MAP61,MAPF6,MAPM1"; + SKY6 = "MAP05,MAP51,MAPMA"; + SKY7 = "MAPM2,MAPM5"; + SKY8 = "MAP07,MAP08,MAP09,MAP52,MAP62,MAPF1"; + SKY10 = "MAP10,MAP12,MAP53,MAP63,MAPM3"; + SKY11 = "MAP11,MAPF7"; + SKY13 = "MAP13,MAP64"; + SKY14 = "MAP14"; + SKY15 = "MAP15,MAP54"; + SKY17 = "MAP70"; + SKY20 = "MAP32,MAP55,MAP65,MAPF2,MAPF5"; + SKY21 = "MAPM4"; + SKY22 = "MAP22,MAP23,MAP25,MAP26,MAP27,MAP56,MAP66,MAPF4,MAPM6"; + SKY30 = "MAP30"; + SKY31 = "MAP31"; + SKY35 = "MAP42"; + SKY40 = "MAP41,MAP71,MAPM9"; + SKY55 = "MAPF3,MAPM8"; + SKY68 = "MAPF8"; + SKY99 = "MAP57,MAPZ0"; + SKY159 = "MAP16"; + SKY172 = "MAP40"; + SKY300 = "MAP72"; + SKY301 = "MAP73"; +} + +// Skill levels +skills +{ + 1 = "Normal"; +} + +// Skins +skins +{ + Sonic; + Tails; + Knuckles; + Amy; + Fang; + Metalsonic; +} + +// Gametypes +gametypes +{ + -1 = "Single Player"; + 0 = "Co-op"; + 1 = "Competition"; + 2 = "Race"; + 3 = "Match"; + 4 = "Team Match"; + 5 = "Tag"; + 6 = "Hide and Seek"; + 7 = "CTF"; +} + +// Texture loading options +defaultwalltexture = "GFZROCK"; +defaultfloortexture = "GFZFLR01"; +defaultceilingtexture = "F_SKY1"; + +// Default texture sets +// (these are not required, but useful for new users) +texturesets +{ +} \ No newline at end of file diff --git a/extras/conf/Includes/SRB222_common.cfg b/extras/conf/Includes/SRB222_common.cfg new file mode 100644 index 000000000..a832e6cef --- /dev/null +++ b/extras/conf/Includes/SRB222_common.cfg @@ -0,0 +1,309 @@ +common +{ + // Some common settings + + + + // Default testing parameters + testparameters = "-file \"%AP\" \"%F\" -warp %L"; + testshortpaths = true; + + // Action special help (mxd) + actionspecialhelp = "https://wiki.srb2.org/wiki/Linedef_type_%K"; + + // Default nodebuilder configurations + defaultsavecompiler = "zennode_normal"; + defaulttestcompiler = "zennode_fast"; + + // Generalized actions + generalizedlinedefs = false; + generalizedsectors = true; + + mixtexturesflats = true; + defaulttexturescale = 1.0f; + defaultflatscale = 1.0f; + scaledtextureoffsets = true; + + // Thing number for start position in 3D Mode + start3dmode = 3328; + + // Texture sources + textures + { + include("SRB222_misc.cfg", "textures"); + } + + // Patch sources + patches + { + include("SRB222_misc.cfg", "patches"); + } + + // Sprite sources + sprites + { + include("SRB222_misc.cfg", "sprites"); + } + + // Flat sources + flats + { + include("SRB222_misc.cfg", "flats"); + } +} + +mapformat_doom +{ + // The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder + formatinterface = "SRB2MapSetIO"; + + /* + GAME DETECT PATTERN + Used to guess the game for which a WAD file is made. + + 1 = One of these lumps must exist + 2 = None of these lumps must exist + 3 = All of these lumps must exist + */ + + gamedetect + { + EXTENDED = 2; + + + BEHAVIOR = 2; + + E#M# = 2; + + MAP?? = 1; + } + + /* + MAP LUMP NAMES + Map lumps are loaded with the map as long as they are right after each other. When the editor + meets a lump which is not defined in this list it will ignore the map if not satisfied. + The order of items defines the order in which lumps will be written to WAD file on save. + To indicate the map header lump, use ~MAP + + Legenda: + required = Lump is required to exist. + blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use) + nodebuild = The nodebuilder generates this lump. + allowempty = The nodebuilder is allowed to leave this lump empty. + script = This lump is a text-based script. Specify the filename of the script configuration to use. + */ + + maplumpnames + { + include("SRB222_misc.cfg", "doommaplumpnames"); + } + + // When this is set to true, sectors with the same tag will light up when a line is highlighted + linetagindicatesectors = true; + + // Special linedefs + include("SRB222_misc.cfg", "speciallinedefs"); + + // Default flags for first new thing (As far as 2.2 goes, they're empty just like in 2.1) + defaultthingflags + { + } + + // DEFAULT SECTOR BRIGHTNESS LEVELS + sectorbrightness + { + include("SRB222_misc.cfg", "sectorbrightness"); + } + + // SECTOR TYPES----------------------------------------------------------------- + sectortypes + { + include("SRB222_sectors.cfg", "sectortypes"); + } + + // GENERALISED SECTOR TYPES----------------------------------------------------------------- + gen_sectortypes + { + include("SRB222_sectors.cfg", "gen_sectortypes"); + } + + // LINEDEF FLAGS + linedefflags + { + include("SRB222_misc.cfg", "linedefflags"); + } + + // Linedef flags UDMF translation table + // This is needed for copy/paste and prefabs to work properly + // When the UDMF field name is prefixed with ! it is inverted + linedefflagstranslation + { + include("SRB222_misc.cfg", "linedefflagstranslation"); + } + + // LINEDEF ACTIVATIONS + linedefactivations + { + } + + // LINEDEF TYPES + linedeftypes + { + include("SRB222_linedefs.cfg", "doom"); + } + + // THING FLAGS + thingflags + { + include("SRB222_misc.cfg", "thingflags"); + } + + // Thing flags UDMF translation table + // This is needed for copy/paste and prefabs to work properly + // When the UDMF field name is prefixed with ! it is inverted + thingflagstranslation + { + include("SRB222_misc.cfg", "thingflagstranslation"); + } + + // THING FLAGS ERROR MASK + // Mask for the thing flags which indicates the options + // that make the same thing appear in the same modes + thingflagsmask1 = 7; // 1 + 2 + 4 + thingflagsmask2 = 0; +} + +mapformat_udmf +{ + // The format interface handles the map data format + formatinterface = "UniversalMapSetIO"; + + // Enables support for long (> 8 chars) texture names + // WARNING: this should only be enabled for UDMF game configurations! + // WARNING: enabling this will make maps incompatible with Doom Builder 2 and can lead to problems in Slade 3! + longtexturenames = false; + + // Default nodebuilder configurations + defaultsavecompiler = "zdbsp_udmf_normal"; + defaulttestcompiler = "zdbsp_udmf_fast"; + + engine = "srb2"; // override that so that DB2 uses the correct namespace + + maplumpnames + { + include("UDMF_misc.cfg", "udmfmaplumpnames_begin"); + include("SRB222_misc.cfg", "udmfmaplumpnames"); + include("UDMF_misc.cfg", "udmfmaplumpnames_end"); + } + + universalfields + { +// include("SRB222_misc.cfg", "universalfields"); + } + + // When this is set to true, sectors with the same tag will light up when a line is highlighted + linetagindicatesectors = false; + + // Special linedefs + include("SRB222_misc.cfg", "speciallinedefs_udmf"); + + // Default flags for first new thing (As far as 2.2 goes, they're empty just like in 2.1) + defaultthingflags + { + } + + // Generalized actions + generalizedlinedefs = false; + + // SECTOR FLAGS + sectorflags + { +// include("SRB222_misc.cfg", "sectorflags"); + } + + // DEFAULT SECTOR BRIGHTNESS LEVELS + sectorbrightness + { + include("SRB222_misc.cfg", "sectorbrightness"); + } + + // SECTOR TYPES + sectortypes + { + include("SRB222_sectors.cfg", "sectortypes"); + } + + // SECTOR RENSERSTYLES +/* sectorrenderstyles + { + include("SRB222_misc.cfg", "sectorrenderstyles"); + }*/ + + // LINEDEF FLAGS + linedefflags + { + include("SRB222_misc.cfg", "linedefflags_udmf"); + } + + // LINEDEF ACTIVATIONS + linedefactivations + { + include("SRB222_misc.cfg", "linedefactivations_udmf"); + } + + linedefflagstranslation + { + } + + + // LINEDEF RENSERSTYLES + linedefrenderstyles + { + include("SRB222_misc.cfg", "linedefrenderstyles"); + } + + //SIDEDEF FLAGS +/* sidedefflags + { + include("UDMF_misc.cfg", "sidedefflags"); + }*/ + + // THING FLAGS + thingflags + { + include("SRB222_misc.cfg", "thingflags_udmf"); + } + + // Thing flags UDMF translation table + // This is needed for copy/paste and prefabs to work properly + // When the UDMF field name is prefixed with ! it is inverted + thingflagstranslation + { + include("SRB222_misc.cfg", "thingflagstranslation"); + } + + // THING RENSERSTYLES +/* thingrenderstyles + { + include("SRB222_misc.cfg", "thingrenderstyles"); + }*/ + + // How to compare thing flags (for the stuck things error checker) +/* thingflagscompare + { + include("UDMF_misc.cfg", "thingflagscompare"); + }*/ + + //mxd. Thing flags UDMF translation table + // This is needed for copy/paste and prefabs to work properly + // When the UDMF field name is prefixed with ! it is inverted + thingflagstranslation + { + } + + // LINEDEF TYPES + linedeftypes + { + include("SRB222_linedefs.cfg", "udmf"); + } +} \ No newline at end of file diff --git a/extras/conf/Includes/SRB222_linedefs.cfg b/extras/conf/Includes/SRB222_linedefs.cfg new file mode 100644 index 000000000..fdf191850 --- /dev/null +++ b/extras/conf/Includes/SRB222_linedefs.cfg @@ -0,0 +1,2486 @@ +doom +{ + misc + { + title = "Miscellaneous"; + + 0 + { + title = "None"; + prefix = "(0)"; + } + + 1 + { + title = "Per-Sector Gravity"; + prefix = "(1)"; + flags64text = "[6] Flip in reverse gravity"; + } + + 5 + { + title = "Camera Scanner"; + prefix = "(5)"; + } + + 7 + { + title = "Sector Flat Alignment"; + prefix = "(7)"; + flags2048text = "[11] Don't align floor"; + flags4096text = "[12] Don't align ceiling"; + flags8192text = "[13] Use texture offsets"; + } + + 10 + { + title = "Culling Plane"; + prefix = "(10)"; + flags64text = "[6] Cull only while in sector"; + } + + 13 + { + title = "Heat Wave Effect"; + prefix = "(13)"; + } + + 40 + { + title = "Visual Portal Between Tagged Linedefs"; + prefix = "(40)"; + } + + 41 + { + title = "Horizon Effect"; + prefix = "(41)"; + } + + 50 + { + title = "Instantly Lower Floor on Level Load"; + prefix = "(50)"; + } + + 51 + { + title = "Instantly Raise Ceiling on Level Load"; + prefix = "(51)"; + } + + 63 + { + title = "Fake Floor/Ceiling Planes"; + prefix = "(63)"; + } + + 540 + { + title = "Floor Friction"; + prefix = "(540)"; + } + } + + parameters + { + title = "Parameters"; + + 2 + { + title = "Custom Exit"; + prefix = "(2)"; + flags2text = "[1] Check emeralds"; + flags64text = "[6] Skip score tally"; + } + + 3 + { + title = "Zoom Tube Parameters"; + prefix = "(3)"; + flags512text = "[9] Ignore player direction"; + } + + 4 + { + title = "Speed Pad Parameters"; + prefix = "(4)"; + flags512text = "[9] No teleport to center"; + flags1024text = "[10] Force spinning frames"; + } + + 8 + { + title = "Special Sector Properties"; + prefix = "(8)"; + flags32text = "[5] Invert precipitation"; + flags64text = "[6] Touch only ceiling"; + flags128text = "[7] Allow opposite gravity"; + flags256text = "[8] Touch sector edge"; + flags512text = "[9] Touch floor or ceiling"; + } + + 9 + { + title = "Chain Parameters"; + prefix = "(9)"; + flags32text = "[5] Swing instead of spin"; + flags64text = "[6] Player-turnable chain"; + flags128text = "[7] Make chain from end item"; + flags256text = "[8] Spawn link at origin"; + flags512text = "[9] Don't clip inside ground"; + flags1024text = "[10] No distance check"; + } + + 11 + { + title = "Rope Hang Parameters"; + prefix = "(11)"; + flags32text = "[5] Don't loop"; + flags64text = "[6] Static"; + } + + 12 + { + title = "Rock Spawner Parameters"; + prefix = "(12)"; + flags64text = "[6] Randomize speed"; + } + + 14 + { + title = "Bustable Block Parameters"; + prefix = "(14)"; + flags32text = "[5] Particles launch from center"; + } + + 15 + { + title = "Fan Particle Spawner Parameters"; + prefix = "(15)"; + } + + 16 + { + title = "Minecart Parameters"; + prefix = "(16)"; + } + + 64 + { + title = "Continuously Appearing/Disappearing FOF"; + prefix = "(64)"; + flags2text = "[1] Use control sector tag"; + flags64text = "[6] No sound effect"; + } + + 65 + { + title = "Bridge Thinker "; + prefix = "(65)"; + } + } + + polyobject + { + title = "PolyObject"; + + 20 + { + title = "First Line"; + prefix = "(20)"; + } + + 21 + { + title = "Explicitly Include Line "; + prefix = "(21)"; + } + + 22 + { + title = "Parameters"; + prefix = "(22)"; + flags64text = "[6] Trigger linedef executor"; + flags128text = "[7] Intangible"; + flags256text = "[8] Stopped by pushables"; + flags512text = "[9] Render flats"; + } + + 30 + { + title = "Waving Flag"; + prefix = "(30)"; + } + + 31 + { + title = "Displacement by Front Sector"; + prefix = "(31)"; + } + + 32 + { + title = "Angular Displacement by Front Sector"; + prefix = "(32)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + } + + planemove + { + title = "Plane Movement"; + + 52 + { + title = "Continuously Falling Sector"; + prefix = "(52)"; + flags64text = "[6] Continuously rising"; + } + + 53 + { + title = "Continuous Floor/Ceiling Mover"; + prefix = "(53)"; + } + + 54 + { + title = "Continuous Floor Mover"; + prefix = "(54)"; + } + + 55 + { + title = "Continuous Ceiling Mover"; + prefix = "(55)"; + } + + 56 + { + title = "Continuous Two-Speed Floor/Ceiling Mover"; + prefix = "(56)"; + } + + 57 + { + title = "Continuous Two-Speed Floor Mover"; + prefix = "(57)"; + } + + 58 + { + title = "Continuous Two-Speed Ceiling Mover"; + prefix = "(58)"; + } + + 59 + { + title = "Activate Moving Platform"; + prefix = "(59)"; + flags64text = "[6] Move upwards at start"; + } + + 60 + { + title = "Activate Moving Platform (Adjustable Speed)"; + prefix = "(60)"; + flags64text = "[6] Move upwards at start"; + } + + 61 + { + title = "Crusher (Ceiling to Floor)"; + prefix = "(61)"; + flags512text = "[9] Double, constant speed"; + } + + 62 + { + title = "Crusher (Floor to Ceiling)"; + prefix = "(62)"; + flags512text = "[9] Double, constant speed"; + } + + 66 + { + title = "Move Floor by Displacement"; + prefix = "(66)"; + flags64text = "[6] Inverse movement"; + } + + 67 + { + title = "Move Ceiling by Displacement"; + prefix = "(67)"; + flags64text = "[6] Inverse movement"; + } + + 68 + { + title = "Move Floor and Ceiling by Displacement"; + prefix = "(68)"; + flags64text = "[6] Inverse movement"; + } + } + + fofsolid + { + title = "FOF (solid)"; + + 100 + { + title = "Solid, Opaque"; + prefix = "(100)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 101 + { + title = "Solid, Opaque, No Shadow"; + prefix = "(101)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1DF"; + } + + 102 + { + title = "Solid, Translucent"; + prefix = "(102)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Render insides"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "195F"; + flags643dfloorflagsadd = "7C80"; + } + + 103 + { + title = "Solid, Sides Only"; + prefix = "(103)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1CF"; + } + + 104 + { + title = "Solid, No Sides"; + prefix = "(104)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1D7"; + flags643dfloorflagsremove = "40"; + } + + 105 + { + title = "Solid, Invisible"; + prefix = "(105)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "47"; + } + + 140 + { + title = "Intangible from Bottom, Opaque"; + prefix = "(140)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "200841F"; + flags643dfloorflagsadd = "40"; + } + + 141 + { + title = "Intangible from Bottom, Translucent"; + prefix = "(141)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "200191F"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 142 + { + title = "Intangible from Bottom, Translucent, No Sides"; + prefix = "(142)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "2001917"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 143 + { + title = "Intangible from Top, Opaque"; + prefix = "(143)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "400841F"; + flags643dfloorflagsadd = "40"; + } + + 144 + { + title = "Intangible from Top, Translucent"; + prefix = "(144)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "400191F"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 145 + { + title = "Intangible from Top, Translucent, No Sides"; + prefix = "(145)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "4001917"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 146 + { + title = "Only Tangible from Sides"; + prefix = "(146)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "600800F"; + } + } + + fofintangible + { + title = "FOF (intangible)"; + + 120 + { + title = "Water, Opaque"; + prefix = "(120)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "8F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 121 + { + title = "Water, Translucent"; + prefix = "(121)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "9F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 122 + { + title = "Water, Opaque, No Sides"; + prefix = "(122)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 123 + { + title = "Water, Translucent, No Sides"; + prefix = "(123)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "1F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 124 + { + title = "Goo Water, Translucent"; + prefix = "(124)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "209F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 125 + { + title = "Goo Water, Translucent, No Sides"; + prefix = "(125)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "201F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 220 + { + title = "Intangible, Opaque"; + prefix = "(220)"; + flags8text = "[3] Slope skew sides"; + 3dfloor = true; + 3dfloorflags = "8F19"; + } + + 221 + { + title = "Intangible, Translucent"; + prefix = "(221)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Cast shadow"; + 3dfloor = true; + 3dfloorflags = "1B59"; + flags643dfloorflagsremove = "40"; + } + + 222 + { + title = "Intangible, Sides Only"; + prefix = "(222)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Cast shadow"; + 3dfloor = true; + 3dfloorflags = "8249"; + flags643dfloorflagsremove = "240"; + } + + 223 + { + title = "Intangible, Invisible"; + prefix = "(223)"; + 3dfloor = true; + 3dfloorflags = "41"; + } + } + + fofmoving + { + title = "FOF (moving)"; + + 150 + { + title = "Air Bobbing"; + prefix = "(150)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 151 + { + title = "Air Bobbing (Adjustable)"; + prefix = "(151)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 152 + { + title = "Reverse Air Bobbing (Adjustable)"; + prefix = "(152)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 160 + { + title = "Floating, Bobbing"; + prefix = "(160)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "4019F"; + } + + 190 + { + title = "Rising Platform, Solid, Opaque"; + prefix = "(190)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 191 + { + title = "Rising Platform, Solid, Opaque, No Shadow"; + prefix = "(191)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1DF"; + } + + 192 + { + title = "Rising Platform, Solid, Translucent"; + prefix = "(192)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "195F"; + } + + 193 + { + title = "Rising Platform, Solid, Invisible"; + prefix = "(193)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "47"; + } + + 194 + { + title = "Rising Platform, Intangible from Bottom, Opaque"; + prefix = "(194)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash, no shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "200841F"; + flags643dfloorflagsadd = "40"; + } + + 195 + { + title = "Rising Platform, Intangible from Bottom, Translucent"; + prefix = "(195)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash, no shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "2009D1F"; + flags643dfloorflagsadd = "40"; + } + } + + fofcrumbling + { + title = "FOF (crumbling)"; + + 170 + { + title = "Crumbling, Respawn"; + prefix = "(170)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "10019F"; + } + + 171 + { + title = "Crumbling, No Respawn"; + prefix = "(171)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "80019F"; + } + + 172 + { + title = "Crumbling, Respawn, Intangible from Bottom"; + prefix = "(172)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "210841F"; + flags643dfloorflagsadd = "40"; + } + + 173 + { + title = "Crumbling, No Respawn, Intangible from Bottom"; + prefix = "(173)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "218841F"; + flags643dfloorflagsadd = "40"; + } + + 174 + { + title = "Crumbling, Respawn, Int. from Bottom, Translucent"; + prefix = "(174)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "210959F"; + flags643dfloorflagsadd = "40"; + } + + 175 + { + title = "Crumbling, No Respawn, Int. from Bottom, Translucent"; + prefix = "(175)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "218959F"; + flags643dfloorflagsadd = "40"; + } + + 176 + { + title = "Crumbling, Respawn, Floating, Bobbing"; + prefix = "(176)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "14019F"; + } + + 177 + { + title = "Crumbling, No Respawn, Floating, Bobbing"; + prefix = "(177)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1C019F"; + } + + 178 + { + title = "Crumbling, Respawn, Floating"; + prefix = "(178)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "14019F"; + } + + 179 + { + title = "Crumbling, No Respawn, Floating"; + prefix = "(179)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1C019F"; + } + + 180 + { + title = "Crumbling, Respawn, Air Bobbing"; + prefix = "(180)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "10019F"; + } + } + + fofspecial + { + title = "FOF (special)"; + + 200 + { + title = "Light Block"; + prefix = "(200)"; + 3dfloor = true; + 3dfloorflags = "20201"; + } + + 201 + { + title = "Half Light Block"; + prefix = "(201)"; + 3dfloor = true; + 3dfloorflags = "201"; + } + + 202 + { + title = "Fog Block"; + prefix = "(202)"; + 3dfloor = true; + 3dfloorflags = "3EF19"; + } + + 250 + { + title = "Mario Block"; + prefix = "(250)"; + flags32text = "[5] Invisible block"; + flags64text = "[6] Brick block"; + 3dfloor = true; + 3dfloorflags = "40019F"; + } + + 251 + { + title = "Thwomp Block"; + prefix = "(251)"; + flags512text = "[9] Custom crushing sound"; + flags1024text = "[10] Custom speed"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 252 + { + title = "Shatter Block"; + prefix = "(252)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Shatter only from below"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "8800019"; + flags643dfloorflagsadd = "200006"; + } + + 253 + { + title = "Shatter Block, Translucent"; + prefix = "(253)"; + flags8text = "[3] Slope skew sides"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "8801019"; + } + + 254 + { + title = "Bustable Block"; + prefix = "(254)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Strong characters only"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "80001F"; + flags643dfloorflagsadd = "20000000"; + } + + 255 + { + title = "Spin-Bustable Block"; + prefix = "(255)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "1080001F"; + } + + 256 + { + title = "Spin-Bustable Block, Translucent"; + prefix = "(256)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "1080101F"; + } + + 257 + { + title = "Quicksand"; + prefix = "(257)"; + flags8text = "[3] Slope skew sides"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "1008219"; + flags10243dfloorflagsadd = "40000000"; + } + + 258 + { + title = "Laser"; + prefix = "(258)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Don't damage bosses"; + 3dfloor = true; + 3dfloorflags = "959"; + } + + 259 + { + title = "Custom FOF"; + prefix = "(259)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorcustom = true; + } + } + + linedeftrigger + { + title = "Linedef Executor Trigger"; + + 300 + { + title = "Continuous"; + prefix = "(300)"; + } + + 301 + { + title = "Each Time"; + prefix = "(301)"; + flags16384text = "[14] Also trigger on exit"; + } + + 302 + { + title = "Once"; + prefix = "(302)"; + } + + 303 + { + title = "Ring Count - Continuous"; + prefix = "(303)"; + flags2text = "[1] Rings greater or equal"; + flags64text = "[6] Rings less or equal"; + flags512text = "[9] Consider all players"; + } + + 304 + { + title = "Ring Count - Once"; + prefix = "(304)"; + flags2text = "[1] Rings greater or equal"; + flags64text = "[6] Rings less or equal"; + flags512text = "[9] Consider all players"; + } + + 305 + { + title = "Character Ability - Continuous"; + prefix = "(305)"; + } + + 306 + { + title = "Character Ability - Each Time"; + prefix = "(306)"; + flags16384text = "[14] Also trigger on exit"; + } + + 307 + { + title = "Character Ability - Once"; + prefix = "(307)"; + } + + 308 + { + title = "Race Only - Once"; + prefix = "(308)"; + } + + 309 + { + title = "CTF Red Team - Continuous"; + prefix = "(309)"; + } + + 310 + { + title = "CTF Red Team - Each Time"; + prefix = "(310)"; + flags16384text = "[14] Also trigger on exit"; + } + + 311 + { + title = "CTF Blue Team - Continuous"; + prefix = "(311)"; + } + + 312 + { + title = "CTF Blue Team - Each Time"; + prefix = "(312)"; + flags16384text = "[14] Also trigger on exit"; + } + + 313 + { + title = "No More Enemies - Once"; + prefix = "(313)"; + } + + 314 + { + title = "Number of Pushables - Continuous"; + prefix = "(314)"; + flags64text = "[6] Number greater or equal"; + flags512text = "[9] Number less"; + } + + 315 + { + title = "Number of Pushables - Once"; + prefix = "(315)"; + flags64text = "[6] Number greater or equal"; + flags512text = "[9] Number less"; + } + + 317 + { + title = "Condition Set Trigger - Continuous"; + prefix = "(317)"; + } + + 318 + { + title = "Condition Set Trigger - Once"; + prefix = "(318)"; + } + + 319 + { + title = "Unlockable - Continuous"; + prefix = "(319)"; + } + + 320 + { + title = "Unlockable - Once"; + prefix = "(320)"; + } + + 321 + { + title = "Trigger After X Calls - Continuous"; + prefix = "(321)"; + flags64text = "[6] Trigger more than once"; + + } + + 322 + { + title = "Trigger After X Calls - Each Time"; + prefix = "(322)"; + flags64text = "[6] Trigger more than once"; + } + + 323 + { + title = "NiGHTSerize - Each Time"; + prefix = "(323)"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run only if player is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Run if no more mares"; + flags32768text = "[15] Run if player is not NiGHTS"; + } + + 324 + { + title = "NiGHTSerize - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run only if player is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Run if no more mares"; + flags32768text = "[15] Run if player is not NiGHTS"; + prefix = "(324)"; + } + + 325 + { + title = "De-NiGHTSerize - Each Time"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run if anyone is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags32768text = "[15] Run if no one is NiGHTS"; + prefix = "(325)"; + } + + 326 + { + title = "De-NiGHTSerize - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run if anyone is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags32768text = "[15] Run if no one is NiGHTS"; + prefix = "(326)"; + } + + 327 + { + title = "NiGHTS Lap - Each Time"; + flags2text = "[1] Mare >= Front X Offset"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + prefix = "(327)"; + } + + 328 + { + title = "NiGHTS Lap - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + prefix = "(328)"; + } + + 329 + { + title = "Ideya Capture Touch - Each Time"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run regardless of spheres"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Only if not enough spheres"; + flags32768text = "[15] Run when entering Capture"; + prefix = "(329)"; + } + + 330 + { + title = "Ideya Capture Touch - Once"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run regardless of spheres"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags16384text = "[14] Only if not enough spheres"; + flags32768text = "[15] Run when entering Capture"; + prefix = "(330)"; + } + + 331 + { + title = "Player Skin - Continuous"; + flags64text = "[6] Disable for this skin"; + prefix = "(331)"; + } + + 332 + { + title = "Player Skin - Each Time"; + flags64text = "[6] Disable for this skin"; + prefix = "(332)"; + } + + 333 + { + title = "Player Skin - Once"; + flags64text = "[6] Disable for this skin"; + prefix = "(333)"; + } + + 399 + { + title = "Level Load"; + prefix = "(399)"; + } + } + + linedefexecsector + { + title = "Linedef Executor (sector)"; + + 400 + { + title = "Set Tagged Sector's Floor Height/Texture"; + prefix = "(400)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Keep floor flat"; + } + + 401 + { + title = "Set Tagged Sector's Ceiling Height/Texture"; + prefix = "(401)"; + flags8text = "[3] Set delay by backside sector"; + } + + 402 + { + title = "Set Tagged Sector's Light Level"; + prefix = "(402)"; + flags8text = "[3] Set delay by backside sector"; + } + + 409 + { + title = "Change Tagged Sector's Tag"; + prefix = "(409)"; + flags8text = "[3] Set delay by backside sector"; + } + + 410 + { + title = "Change Front Sector's Tag"; + prefix = "(410)"; + flags8text = "[3] Set delay by backside sector"; + } + + 416 + { + title = "Start Adjustable Flickering Light"; + prefix = "(416)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 417 + { + title = "Start Adjustable Pulsating Light"; + prefix = "(417)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 418 + { + title = "Start Adjustable Blinking Light (unsynchronized)"; + prefix = "(418)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 419 + { + title = "Start Adjustable Blinking Light (synchronized)"; + prefix = "(419)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 420 + { + title = "Fade Light Level"; + prefix = "(420)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set params by X/Y offsets"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + } + + 421 + { + title = "Stop Lighting Effect"; + prefix = "(421)"; + flags8text = "[3] Set delay by backside sector"; + } + + 435 + { + title = "Change Plane Scroller Direction"; + prefix = "(435)"; + flags8text = "[3] Set delay by backside sector"; + } + } + + linedefexecplane + { + title = "Linedef Executor (plane movement)"; + + 403 + { + title = "Move Tagged Sector's Floor"; + prefix = "(403)"; + flags2text = "[1] Trigger linedef executor"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Change floor flat"; + } + + 404 + { + title = "Move Tagged Sector's Ceiling"; + prefix = "(404)"; + flags2text = "[1] Trigger linedef executor"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Change ceiling flat"; + } + + 405 + { + title = "Move Floor According to Front Texture Offsets"; + prefix = "(405)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move instantly"; + } + + 407 + { + title = "Move Ceiling According to Front Texture Offsets"; + prefix = "(407)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move instantly"; + } + + 411 + { + title = "Stop Plane Movement"; + prefix = "(411)"; + flags8text = "[3] Set delay by backside sector"; + } + + 428 + { + title = "Start Platform Movement"; + prefix = "(428)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move upwards at start"; + } + + 429 + { + title = "Crush Ceiling Once"; + prefix = "(429)"; + flags8text = "[3] Set delay by backside sector"; + flags512text = "[9] Double, constant speed"; + } + + 430 + { + title = "Crush Floor Once"; + prefix = "(430)"; + flags8text = "[3] Set delay by backside sector"; + } + + 431 + { + title = "Crush Floor and Ceiling Once"; + prefix = "(431)"; + flags8text = "[3] Set delay by backside sector"; + flags512text = "[9] Double, constant speed"; + } + } + + linedefexecplayer + { + title = "Linedef Executor (player/object)"; + + 412 + { + title = "Teleporter"; + prefix = "(412)"; + flags2text = "[1] Silent"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Retain angle"; + flags256text = "[8] Relative, silent"; + flags512text = "[9] Retain momentum"; + } + + 425 + { + title = "Change Object State"; + prefix = "(425)"; + flags8text = "[3] Set delay by backside sector"; + } + + 426 + { + title = "Stop Object"; + prefix = "(426)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Teleport to sector center"; + } + + 427 + { + title = "Award Score"; + prefix = "(427)"; + flags8text = "[3] Set delay by backside sector"; + } + + 432 + { + title = "Enable/Disable 2D Mode"; + prefix = "(432)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Return to 3D"; + } + + 433 + { + title = "Enable/Disable Gravity Flip"; + prefix = "(433)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Return to normal"; + } + + 434 + { + title = "Award Power-Up"; + prefix = "(434)"; + flags2text = "[1] Use back upper texture"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] No time limit"; + } + + 437 + { + title = "Disable Player Control"; + prefix = "(437)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Allow jumping"; + } + + 438 + { + title = "Change Object Size"; + prefix = "(438)"; + flags8text = "[3] Set delay by backside sector"; + } + + 442 + { + title = "Change Object Type State"; + prefix = "(442)"; + flags8text = "[3] Set delay by backside sector"; + } + + 457 + { + title = "Track Object's Angle"; + prefix = "(457)"; + flags8text = "[3] Set delay by backside sector"; + flags128text = "[7] Don't stop after first fail"; + } + + 458 + { + title = "Stop Tracking Object's Angle"; + prefix = "(458)"; + flags8text = "[3] Set delay by backside sector"; + } + + 460 + { + title = "Award Rings"; + prefix = "(460)"; + } + + 461 + { + title = "Spawn Object"; + prefix = "(461)"; + flags64text = "[6] Spawn inside a range"; + } + + 462 + { + title = "Stop Timer/Exit Stage in Record Attack"; + prefix = "(462)"; + } + } + + linedefexecmisc + { + title = "Linedef Executor (misc.)"; + + 413 + { + title = "Change Music"; + prefix = "(413)"; + flags2text = "[1] Keep after death"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Seek to current song position"; + flags64text = "[6] For everyone"; + flags128text = "[7] Fade to custom volume"; + flags512text = "[9] Don't loop"; + flags16384text = "[14] Force music reload"; + } + + 414 + { + title = "Play Sound Effect"; + prefix = "(414)"; + flags2text = "[1] From calling sector"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] From nowhere for triggerer"; + flags512text = "[9] For everyone"; + flags1024text = "[10] From tagged sectors"; + } + + 415 + { + title = "Run Script"; + prefix = "(415)"; + flags8text = "[3] Set delay by backside sector"; + } + + 422 + { + title = "Switch to Cut-Away View"; + prefix = "(422)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Adjust pitch"; + } + + 423 + { + title = "Change Sky"; + prefix = "(423)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + } + + 424 + { + title = "Change Weather"; + prefix = "(424)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + } + + 436 + { + title = "Shatter FOF"; + prefix = "(436)"; + flags8text = "[3] Set delay by backside sector"; + } + + 439 + { + title = "Change Tagged Linedef's Textures"; + prefix = "(439)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only existing"; + } + + 440 + { + title = "Start Metal Sonic Race"; + prefix = "(440)"; + flags8text = "[3] Set delay by backside sector"; + } + + 441 + { + title = "Condition Set Trigger"; + prefix = "(441)"; + flags8text = "[3] Set delay by backside sector"; + } + + 443 + { + title = "Call Lua Function"; + prefix = "(443)"; + flags8text = "[3] Set delay by backside sector"; + } + + 444 + { + title = "Earthquake"; + prefix = "(444)"; + flags8text = "[3] Set delay by backside sector"; + } + + + 445 + { + title = "Make FOF Disappear/Reappear"; + prefix = "(445)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Reappear"; + } + + 446 + { + title = "Make FOF Crumble"; + prefix = "(446)"; + flags2text = "[1] Flags determine respawn"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't respawn"; + } + + 447 + { + title = "Change Tagged Sector's Colormap"; + prefix = "(447)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Front X/Y = Alpha"; + flags32text = "[5] Subtract Red value"; + flags64text = "[6] Subtract Green value"; + flags128text = "[7] Subtract Blue value"; + flags256text = "[8] Calc relative values"; + flags32768text = "[15] Use back side colormap"; + } + + 448 + { + title = "Change Skybox"; + prefix = "(448)"; + flags2text = "[1] Change centerpoint"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + flags512text = "[9] Don't change viewpoint"; + } + + 450 + { + title = "Execute Linedef Executor (specific tag)"; + prefix = "(450)"; + flags8text = "[3] Set delay by backside sector"; + } + + 451 + { + title = "Execute Linedef Executor (random tag in range)"; + prefix = "(451)"; + flags8text = "[3] Set delay by backside sector"; + } + + 452 + { + title = "Set FOF Translucency"; + prefix = "(452)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Do not handle FF_TRANS"; + flags256text = "[8] Set relative to current val"; + } + + 453 + { + title = "Fade FOF"; + prefix = "(453)"; + flags2text = "[1] Do not handle FF_EXISTS"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] No collision during fade"; + flags64text = "[6] Do not handle FF_TRANS"; + flags128text = "[7] Do not handle lighting"; + flags256text = "[8] Set relative to current val"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Do not handle collision"; + flags32768text = "[15] Use exact alpha in OGL"; + } + + 454 + { + title = "Stop Fading FOF"; + prefix = "(454)"; + flags2text = "[1] Do not finalize collision"; + flags8text = "[3] Set delay by backside sector"; + } + + 455 + { + title = "Fade Tagged Sector's Colormap"; + prefix = "(455)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Front X/Y = Alpha"; + flags32text = "[5] Subtract Red value"; + flags64text = "[6] Subtract Green value"; + flags128text = "[7] Subtract Blue value"; + flags256text = "[8] Calc relative values"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Fade from invisible black"; + flags32768text = "[15] Use back side colormap"; + } + + 456 + { + title = "Stop Fading Tagged Sector's Colormap"; + prefix = "(456)"; + flags8text = "[3] Set delay by backside sector"; + } + + 459 + { + title = "Control Text Prompt"; + prefix = "(459)"; + flags2text = "[1] Close text prompt"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Run executor tag on close"; + flags64text = "[6] For everyone"; + flags128text = "[7] Do not block controls"; + flags256text = "[8] Do not freeze time"; + flags32768text = "[15] Find prompt by name"; + } + } + + linedefexecpoly + { + title = "Linedef Executor (polyobject)"; + + 480 + { + title = "Door Slide"; + prefix = "(480)"; + flags8text = "[3] Set delay by backside sector"; + } + + 481 + { + title = "Door Swing"; + prefix = "(481)"; + flags8text = "[3] Set delay by backside sector"; + } + + 482 + { + title = "Move"; + prefix = "(482)"; + flags8text = "[3] Set delay by backside sector"; + } + + 483 + { + title = "Move, Override"; + prefix = "(483)"; + flags8text = "[3] Set delay by backside sector"; + } + + 484 + { + title = "Rotate Right"; + prefix = "(484)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 485 + { + title = "Rotate Right, Override"; + prefix = "(485)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 486 + { + title = "Rotate Left"; + prefix = "(486)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 487 + { + title = "Rotate Left, Override"; + prefix = "(487)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 488 + { + title = "Move by Waypoints"; + prefix = "(488)"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Reverse order"; + flags128text = "[7] There and back"; + flags256text = "[8] Return when done"; + flags512text = "[9] Loop movement"; + } + + 489 + { + title = "Turn Invisible, Intangible"; + prefix = "(489)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only invisible"; + } + + 490 + { + title = "Turn Visible, Tangible"; + prefix = "(490)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only visible"; + } + + 491 + { + title = "Set Translucency"; + prefix = "(491)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set raw alpha by Front X"; + flags256text = "[8] Calc relative values"; + } + + 492 + { + title = "Fade Translucency"; + prefix = "(492)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set raw alpha by Front X"; + flags32text = "[5] No collision during fade"; + flags256text = "[8] Calc relative values"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Do not handle collision"; + } + } + + wallscroll + { + title = "Wall Scrolling"; + + 500 + { + title = "Scroll Wall Front Side Left"; + prefix = "(500)"; + } + + 501 + { + title = "Scroll Wall Front Side Right"; + prefix = "(501)"; + } + + 502 + { + title = "Scroll Wall According to Linedef"; + prefix = "(502)"; + } + + 503 + { + title = "Scroll Wall According to Linedef (Accelerative)"; + prefix = "(503)"; + } + + 504 + { + title = "Scroll Wall According to Linedef (Displacement)"; + prefix = "(504)"; + } + + 505 + { + title = "Scroll Texture by Front Side Offsets"; + prefix = "(505)"; + } + + 506 + { + title = "Scroll Texture by Back Side Offsets"; + prefix = "(506)"; + } + } + + planescroll + { + title = "Plane Scrolling"; + + 510 + { + title = "Scroll Floor Texture"; + prefix = "(510)"; + } + + 511 + { + title = "Scroll Floor Texture (Accelerative)"; + prefix = "(511)"; + } + + 512 + { + title = "Scroll Floor Texture (Displacement)"; + prefix = "(512)"; + } + + 513 + { + title = "Scroll Ceiling Texture"; + prefix = "(513)"; + } + + 514 + { + title = "Scroll Ceiling Texture (Accelerative)"; + prefix = "(514)"; + } + + 515 + { + title = "Scroll Ceiling Texture (Displacement)"; + prefix = "(515)"; + } + + 520 + { + title = "Carry Objects on Floor"; + prefix = "(520)"; + } + + 521 + { + title = "Carry Objects on Floor (Accelerative)"; + prefix = "(521)"; + flags64text = "[6] Even across edges"; + } + + 522 + { + title = "Carry Objects on Floor (Displacement)"; + prefix = "(522)"; + } + + 523 + { + title = "Carry Objects on Ceiling"; + prefix = "(523)"; + flags64text = "[6] Even across edges"; + } + + 524 + { + title = "Carry Objects on Ceiling (Accelerative)"; + prefix = "(524)"; + } + + 525 + { + title = "Carry Objects on Ceiling (Displacement)"; + prefix = "(525)"; + } + + 530 + { + title = "Scroll Floor Texture and Carry Objects"; + prefix = "(530)"; + flags64text = "[6] Even across edges"; + } + + 531 + { + title = "Scroll Floor Texture and Carry Objects (Accelerative)"; + prefix = "(531)"; + } + + 532 + { + title = "Scroll Floor Texture and Carry Objects (Displacement)"; + prefix = "(532)"; + } + + 533 + { + title = "Scroll Ceiling Texture and Carry Objects"; + prefix = "(533)"; + flags64text = "[6] Even across edges"; + } + + 534 + { + title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; + prefix = "(534)"; + } + + 535 + { + title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; + prefix = "(535)"; + } + } + + pusher + { + title = "Pusher"; + + 541 + { + title = "Wind"; + prefix = "(541)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 542 + { + title = "Upwards Wind"; + prefix = "(542)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 543 + { + title = "Downwards Wind"; + prefix = "(543)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 544 + { + title = "Current"; + prefix = "(544)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 545 + { + title = "Upwards Current"; + prefix = "(545)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 546 + { + title = "Downwards Current"; + prefix = "(546)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 547 + { + title = "Push/Pull"; + prefix = "(547)"; + } + } + + light + { + title = "Lighting"; + + 600 + { + title = "Floor Lighting"; + prefix = "(600)"; + } + + 601 + { + title = "Ceiling Lighting"; + prefix = "(601)"; + } + + 602 + { + title = "Adjustable Pulsating Light"; + prefix = "(602)"; + } + + 603 + { + title = "Adjustable Flickering Light"; + prefix = "(603)"; + } + + 604 + { + title = "Adjustable Blinking Light (unsynchronized)"; + prefix = "(604)"; + } + + 605 + { + title = "Adjustable Blinking Light (synchronized)"; + prefix = "(605)"; + } + + 606 + { + title = "Colormap"; + prefix = "(606)"; + } + } + + slope + { + title = "Slope"; + + 700 + { + title = "Slope Frontside Floor"; + prefix = "(700)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 1; + } + + 701 + { + title = "Slope Frontside Ceiling"; + prefix = "(701)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 2; + } + + 702 + { + title = "Slope Frontside Floor and Ceiling"; + prefix = "(702)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 3; + } + + 703 + { + title = "Slope Frontside Floor and Backside Ceiling"; + prefix = "(703)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 9; + } + + 704 + { + title = "Slope Frontside Floor by 3 Tagged Vertex Things"; + prefix = "(704)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 0; + } + + 705 + { + title = "Slope Frontside Ceiling by 3 Tagged Vertex Things"; + prefix = "(705)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 1; + } + + 710 + { + title = "Slope Backside Floor"; + prefix = "(710)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 4; + } + + 711 + { + title = "Slope Backside Ceiling"; + prefix = "(711)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 8; + } + + 712 + { + title = "Slope Backside Floor and Ceiling"; + prefix = "(712)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 12; + } + + 713 + { + title = "Slope Backside Floor and Frontside Ceiling"; + prefix = "(713)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + slope = "regular"; + slopeargs = 6; + } + + 714 + { + title = "Slope Backside Floor by 3 Tagged Vertex Things"; + prefix = "(714)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 2; + } + + 715 + { + title = "Slope Backside Ceiling by 3 Tagged Vertex Things"; + prefix = "(715)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 3; + } + + 720 + { + title = "Copy Frontside Floor Slope from Line Tag"; + prefix = "(720)"; + slope = "copy"; + slopeargs = 1; + } + + 721 + { + title = "Copy Frontside Ceiling Slope from Line Tag"; + prefix = "(721)"; + slope = "copy"; + slopeargs = 2; + } + + 722 + { + title = "Copy Frontside Floor and Ceiling Slope from Line Tag"; + prefix = "(722)"; + slope = "copy"; + slopeargs = 3; + } + + 799 + { + title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; + prefix = "(799)"; + } + } + + transwall + { + title = "Translucent Wall"; + + 900 + { + title = "90% Opaque"; + prefix = "(900)"; + } + + 901 + { + title = "80% Opaque"; + prefix = "(901)"; + } + + 902 + { + title = "70% Opaque"; + prefix = "(902)"; + } + + 903 + { + title = "60% Opaque"; + prefix = "(903)"; + } + + 904 + { + title = "50% Opaque"; + prefix = "(904)"; + } + + 905 + { + title = "40% Opaque"; + prefix = "(905)"; + } + + 906 + { + title = "30% Opaque"; + prefix = "(906)"; + } + + 907 + { + title = "20% Opaque"; + prefix = "(907)"; + } + + 908 + { + title = "10% Opaque"; + prefix = "(908)"; + } + + 909 + { + title = "Fog Wall"; + prefix = "(909)"; + } + } +} + +udmf +{ + misc + { + title = "Miscellaneous"; + + 0 + { + title = "None"; + prefix = "(0)"; + } + } +} \ No newline at end of file diff --git a/extras/conf/Includes/SRB222_misc.cfg b/extras/conf/Includes/SRB222_misc.cfg new file mode 100644 index 000000000..ce23388b2 --- /dev/null +++ b/extras/conf/Includes/SRB222_misc.cfg @@ -0,0 +1,726 @@ +linedefflags +{ + 1 = "[0] Impassable"; + 2 = "[1] Block Enemies"; + 4 = "[2] Double-Sided"; + 8 = "[3] Upper Unpegged"; + 16 = "[4] Lower Unpegged"; + 32 = "[5] Slope Skew (E1)"; + 64 = "[6] Not Climbable"; + 128 = "[7] No Midtexture Skew (E2)"; + 256 = "[8] Peg Midtexture (E3)"; + 512 = "[9] Solid Midtexture (E4)"; + 1024 = "[10] Repeat Midtexture (E5)"; + 2048 = "[11] Netgame Only"; + 4096 = "[12] No Netgame"; + 8192 = "[13] Effect 6"; + 16384 = "[14] Bouncy Wall"; + 32768 = "[15] Transfer Line"; +} + + +// LINEDEF ACTIVATIONS +// Make sure these are in order from lowest value to highest value +linedefactivations +{ +} + + +// Linedef flags UDMF translation table +// This is needed for copy/paste and prefabs to work properly +// When the UDMF field name is prefixed with ! it is inverted +linedefflagstranslation +{ + 1 = "blocking"; + 2 = "blockmonsters"; + 4 = "twosided"; + 8 = "dontpegtop"; + 16 = "dontpegbottom"; + 32 = "skewtd"; + 64 = "noclimb"; + 128 = "noskew"; + 256 = "midpeg"; + 512 = "midsolid"; + 1024 = "wrapmidtex"; + 2048 = "netonly"; + 4096 = "nonet"; + 8192 = "effect6"; + 16384 = "bouncy"; + 32768 = "transfer"; +} + + +linedefflags_udmf +{ + blocking = "Impassable"; + blockmonsters = "Block Enemies"; + twosided = "Double-Sided"; + dontpegtop = "Upper Unpegged"; + dontpegbottom = "Lower Unpegged"; + skewtd = "Slope Skew"; + noclimb = "Not Climbable"; + noskew = "No Midtexture Skew"; + midpeg = "Peg Midtexture"; + midsolid = "Solid Midtexture"; + wrapmidtex = "Repeat Midtexture"; +// netonly = "Netgame-Only special"; +// nonet = "No netgame special"; +// effect6 = "Effect 6"; + bouncy = "Bouncy Wall"; +// transfer = "Transfer Line"; +} + + +linedefactivations_udmf +{ + notriggerorder = "Out of Order"; + netonly = "Netgame-Only"; + nonet = "No netgame"; +} + +sidedefflags +{ + clipmidtex = "Clip middle texture"; + wrapmidtex = "Wrap middle texture"; + smoothlighting = "Smooth lighting"; + nofakecontrast = "Even lighting"; + nodecals = "No decals"; + lightfog = "Use sidedef brightness on fogged walls"; +} + +//RENDER STYLES +thingrenderstyles +{ +} + +linedefrenderstyles +{ + translucent = "Translucent"; + fog = "Fog"; +} + +sectorrenderstyles +{ +} + +thingflags +{ + 1 = "[1] Extra"; + 2 = "[2] Flip"; + 4 = "[4] Special"; + 8 = "[8] Ambush"; +} + +// THING FLAGS +thingflags_udmf +{ + extra = "Extra"; + flip = "Flip"; + special = "Special"; + ambush = "Ambush"; +} + + +// Thing flags UDMF translation table +// This is needed for copy/paste and prefabs to work properly +// When the UDMF field name is prefixed with ! it is inverted +thingflagstranslation +{ + 1 = "extra"; + 2 = "flip"; + 4 = "special"; + 8 = "ambush"; +} + + +// DEFAULT SECTOR BRIGHTNESS LEVELS +sectorbrightness +{ + 255; + 248; + 240; + 232; + 224; + 216; + 208; + 200; + 192; + 184; + 176; + 168; + 160; + 152; + 144; + 136; + 128; + 120; + 112; + 104; + 96; + 88; + 80; + 72; + 64; + 56; + 48; + 40; + 32; + 24; + 16; + 8; + 0; +} + +/* +TEXTURES AND FLAT SOURCES +This tells Doom Builder where to find the information for textures +and flats in the IWAD file, Addition WAD file and Map WAD file. + +Start and end lumps must be given in a structure (of which the +key name doesnt matter) and any textures or flats in between them +are loaded in either the textures category or flats category. + +For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. +*/ +textures +{ + zdoom1 + { + start = "TX_START"; + end = "TX_END"; + } +} + +/* +ADDITIONAL UNIVERSAL DOOM MAP FORMAT FIELD DEFINITIONS +Only add fields here that Doom Builder does not edit with its own user-interface! +The "default" field must match the UDMF specifications! + +Field data types: +0 = integer * +1 = float +2 = string +3 = bool +4 = linedef action (integer) * +5 = sector effect (integer) * +6 = texture (string) +7 = flat (string) +8 = angle in degrees (integer) +9 = angle in radians (float) +10 = XXRRGGBB color (integer) +11 = enum option (integer) * +12 = enum bits (integer) * +13 = sector tag (integer) * +14 = thing tag (integer) * +15 = linedef tag (integer) * +16 = enum option (string) +17 = angle in degrees (float) +22 = byte angle (integer) +*/ +universalfields +{ + sector + { + friction + { + name = "Friction"; + type = 1; + default = 1; + } + + specialeffectplanes + { + type = 11; + enum = "floorceiling"; + default = 0; + } + + colormapbegin + { + type = 0; + default = 0; + } + + colormapend + { + type = 0; + default = 33; + } + + foglighting + { + type = 3; + default = false; + } + + teambase + { + type = 11; + enum = "ctfteam"; + default = 0; + } + + triggersector + { + type = 3; + default = false; + } + + triggerobject + { + type = 11; + enum = "triggerobjects"; + default = 0; + } + + triggersurface + { + type = 11; + enum = "triggersurfaces"; + default = 0; + } + + ringdrain + { + type = 1; + default = 0; + } + } + + linedef + { + executordelay + { + type = 0; + default = 0; + } + midtexrepetitions + { + type = 0; + default = 0; + } + arg5 + { + type = 0; + default = 0; + } + arg1str + { + type = 2; + default = ""; + } + } + + thing + { + } +} + +/* +MAP LUMP NAMES +Map lumps are loaded with the map as long as they are right after each other. When the editor +meets a lump which is not defined in this list it will ignore the map if not satisfied. +The order of items defines the order in which lumps will be written to WAD file on save. +To indicate the map header lump, use ~MAP + +Legenda: +required = Lump is required to exist. +blindcopy = Lump will be copied along with the map blindly. (useful for lumps Doom Builder doesn't use) +nodebuild = The nodebuilder generates this lump. +allowempty = The nodebuilder is allowed to leave this lump empty. +scriptbuild = This lump is a text-based script, which should be compiled using current script compiler; +script = This lump is a text-based script. Specify the filename of the script configuration to use. +*/ + +doommaplumpnames +{ + ~MAP + { + required = true; + blindcopy = true; + nodebuild = false; + } + + THINGS + { + required = true; + nodebuild = true; + allowempty = true; + } + + LINEDEFS + { + required = true; + nodebuild = true; + allowempty = false; + } + + SIDEDEFS + { + required = true; + nodebuild = true; + allowempty = false; + } + + VERTEXES + { + required = true; + nodebuild = true; + allowempty = false; + } + + SEGS + { + required = false; + nodebuild = true; + allowempty = false; + } + + SSECTORS + { + required = false; + nodebuild = true; + allowempty = false; + } + + NODES + { + required = false; + nodebuild = true; + allowempty = false; + } + + SECTORS + { + required = true; + nodebuild = true; + allowempty = false; + } + + REJECT + { + required = false; + nodebuild = true; + allowempty = false; + } + + BLOCKMAP + { + required = false; + nodebuild = true; + allowempty = true; + } +} + +udmfmaplumpnames +{ + ZNODES + { + required = false; + nodebuild = true; + allowempty = false; + } + + REJECT + { + required = false; + nodebuild = true; + allowempty = false; + } + + BLOCKMAP + { + required = false; + nodebuild = true; + allowempty = true; + } +} + +// ENUMERATIONS +// These are enumerated lists for linedef types and UDMF fields. +// Reserved names are: angledeg, anglerad, color, texture, flat +enums +{ + falsetrue + { + 0 = "False"; + 1 = "True"; + } + + yesno + { + 0 = "Yes"; + 1 = "No"; + } + + noyes + { + 0 = "No"; + 1 = "Yes"; + } + + onoff + { + 0 = "On"; + 1 = "Off"; + } + + offon + { + 0 = "Off"; + 1 = "On"; + } + + updown + { + 0 = "Up"; + 1 = "Down"; + } + + downup + { + 0 = "Down"; + 1 = "Up"; + } + + addset + { + 0 = "Add"; + 1 = "Set"; + } + + floorceiling + { + 0 = "Floor"; + 1 = "Ceiling"; + 2 = "Floor and ceiling"; + } + + triggertype + { + 0 = "Continuous"; + 1 = "Each Time (Enter)"; + 2 = "Each Time (Enter and leave)"; + 3 = "Once"; + } + + frontback + { + 0 = "None"; + 1 = "Front"; + 2 = "Back"; + } + + ctfteam + { + 0 = "None"; + 1 = "Red"; + 2 = "Blue"; + } + + triggerobjects + { + 0 = "Any player"; + 1 = "All players"; + 2 = "Pushable object"; + 3 = "Any object with thinker"; + } + + triggersurfaces + { + 0 = "Floor touch"; + 1 = "Ceiling touch"; + 2 = "Floor or ceiling touch"; + 3 = "Anywhere in sector"; + } + + tangibility + { + 1 = "Intangible from top"; + 2 = "Intangible from bottom"; + 4 = "Don't block players"; + 8 = "Don't block non-players"; + } +} + +//Default things filters +thingsfilters +{ + + filter0 + { + name = "Player starts"; + category = "starts"; + type = -1; + } + + + filter1 + { + name = "Enemies"; + category = "enemies"; + type = -1; + + } + + + filter2 + { + name = "NiGHTS Track"; + category = "nightstrk"; + type = -1; + + } + + + filter3 + { + name = "Normal Gravity"; + category = ""; + type = -1; + + fields + { + 2 = false; + } + + } + + + filter4 + { + name = "Reverse Gravity"; + category = ""; + type = -1; + + fields + { + 2 = true; + } + + } +} + +thingsfilters_udmf +{ +} + +// Special linedefs +speciallinedefs +{ + soundlinedefflag = 64; // See linedefflags + singlesidedflag = 1; // See linedefflags + doublesidedflag = 4; // See linedefflags + impassableflag = 1; + upperunpeggedflag = 8; + lowerunpeggedflag = 16; + repeatmidtextureflag = 1024; + pegmidtextureflag = 256; +} + +speciallinedefs_udmf +{ + soundlinedefflag = "noclimb"; + singlesidedflag = "blocking"; + doublesidedflag = "twosided"; + impassableflag = "blocking"; + upperunpeggedflag = "dontpegtop"; + lowerunpeggedflag = "dontpegbottom"; + repeatmidtextureflag = "wrapmidtex"; + pegmidtextureflag = "midpeg"; +} + +scriptlumpnames +{ + MAINCFG + { + script = "SOC.cfg"; + } + + OBJCTCFG + { + script = "SOC.cfg"; + } + + SOC_ + { + script = "SOC.cfg"; + isprefix = true; + } + + LUA_ + { + script = "Lua.cfg"; + isprefix = true; + } +} + +// Texture sources +textures +{ + zdoom1 + { + start = "TX_START"; + end = "TX_END"; + } +} + +// Patch sources +patches +{ + standard1 + { + start = "P_START"; + end = "P_END"; + } + + standard2 + { + start = "PP_START"; + end = "PP_END"; + } +} + +// Sprite sources +sprites +{ + standard1 + { + start = "S_START"; + end = "S_END"; + } + + standard2 + { + start = "SS_START"; + end = "SS_END"; + } +} + +// Flat sources +flats +{ + standard1 + { + start = "F_START"; + end = "F_END"; + } + + standard2 + { + start = "FF_START"; + end = "FF_END"; + } + + standard3 + { + start = "FF_START"; + end = "F_END"; + } + + standard4 + { + start = "F_START"; + end = "FF_END"; + } +} \ No newline at end of file diff --git a/extras/conf/Includes/SRB222_sectors.cfg b/extras/conf/Includes/SRB222_sectors.cfg new file mode 100644 index 000000000..3bcbeb1b1 --- /dev/null +++ b/extras/conf/Includes/SRB222_sectors.cfg @@ -0,0 +1,109 @@ +sectortypes +{ + 0 = "Normal"; + 1 = "Damage"; + 2 = "Damage (Water)"; + 3 = "Damage (Fire)"; + 4 = "Damage (Electrical)"; + 5 = "Spikes"; + 6 = "Death Pit (Camera Tilt)"; + 7 = "Death Pit (No Camera Tilt)"; + 8 = "Instant Kill"; + 9 = "Ring Drainer (Floor Touch)"; + 10 = "Ring Drainer (Anywhere in Sector)"; + 11 = "Special Stage Damage"; + 12 = "Space Countdown"; + 13 = "Ramp Sector (double step-up/down)"; + 14 = "Non-Ramp Sector (no step-down)"; + 15 = "Bouncy FOF"; + 16 = "Trigger Line Ex. (Pushable Objects)"; + 32 = "Trigger Line Ex. (Anywhere, All Players)"; + 48 = "Trigger Line Ex. (Floor Touch, All Players)"; + 64 = "Trigger Line Ex. (Anywhere in Sector)"; + 80 = "Trigger Line Ex. (Floor Touch)"; + 96 = "Trigger Line Ex. (Emerald Check)"; + 112 = "Trigger Line Ex. (NiGHTS Mare)"; + 128 = "Check for Linedef Executor on FOFs"; + 144 = "Egg Capsule"; + 160 = "Special Stage Time/Rings Parameters"; + 176 = "Custom Global Gravity"; + 512 = "Wind/Current"; + 1024 = "Conveyor Belt"; + 1280 = "Speed Pad"; + 4096 = "Star Post Activator"; + 8192 = "Exit/Special Stage Pit/Return Flag"; + 12288 = "CTF Red Team Base"; + 16384 = "CTF Blue Team Base"; + 20480 = "Fan Sector"; + 24576 = "Super Sonic Transform"; + 28672 = "Force Spin"; + 32768 = "Zoom Tube Start"; + 36864 = "Zoom Tube End"; + 40960 = "Circuit Finish Line"; + 45056 = "Rope Hang"; + 49152 = "Intangible to the Camera"; +} + +gen_sectortypes +{ + first + { + 0 = "Normal"; + 1 = "Damage"; + 2 = "Damage (Water)"; + 3 = "Damage (Fire)"; + 4 = "Damage (Electrical)"; + 5 = "Spikes"; + 6 = "Death Pit (Camera Tilt)"; + 7 = "Death Pit (No Camera Tilt)"; + 8 = "Instant Kill"; + 9 = "Ring Drainer (Floor Touch)"; + 10 = "Ring Drainer (Anywhere in Sector)"; + 11 = "Special Stage Damage"; + 12 = "Space Countdown"; + 13 = "Ramp Sector (double step-up/down)"; + 14 = "Non-Ramp Sector (no step-down)"; + 15 = "Bouncy FOF"; + } + + second + { + 0 = "Normal"; + 16 = "Trigger Line Ex. (Pushable Objects)"; + 32 = "Trigger Line Ex. (Anywhere, All Players)"; + 48 = "Trigger Line Ex. (Floor Touch, All Players)"; + 64 = "Trigger Line Ex. (Anywhere in Sector)"; + 80 = "Trigger Line Ex. (Floor Touch)"; + 96 = "Trigger Line Ex. (Emerald Check)"; + 112 = "Trigger Line Ex. (NiGHTS Mare)"; + 128 = "Check for Linedef Executor on FOFs"; + 144 = "Egg Capsule"; + 160 = "Special Stage Time/Rings Parameters"; + 176 = "Custom Global Gravity"; + } + + third + { + 0 = "Normal"; + 512 = "Wind/Current"; + 1024 = "Conveyor Belt"; + 1280 = "Speed Pad"; + } + + fourth + { + 0 = "Normal"; + 4096 = "Star Post Activator"; + 8192 = "Exit/Special Stage Pit/Return Flag"; + 12288 = "CTF Red Team Base"; + 16384 = "CTF Blue Team Base"; + 20480 = "Fan Sector"; + 24576 = "Super Sonic Transform"; + 28672 = "Force Spin"; + 32768 = "Zoom Tube Start"; + 36864 = "Zoom Tube End"; + 40960 = "Circuit Finish Line"; + 45056 = "Rope Hang"; + 49152 = "Intangible to the Camera"; + } +} \ No newline at end of file diff --git a/extras/conf/Includes/SRB222_things.cfg b/extras/conf/Includes/SRB222_things.cfg new file mode 100644 index 000000000..194e43630 --- /dev/null +++ b/extras/conf/Includes/SRB222_things.cfg @@ -0,0 +1,3398 @@ +// THING TYPES------------------------------------------------------------------ +// Color values: 1-Dark_Blue 2-Dark_Green 3-Turqoise 4-Dark_Red 5-Purple 6-Brown 7-Gray +// 8-Dark_Gray 9-Blue 10-Green 11-Cyan 12-Red 13-Magenta +// 14-Yellow 15-White 16-Pink 17-Orange 18-Gold 19-Cream + +editor +{ + color = 15; // White + arrow = 1; + title = ""; + error = -1; + width = 8; + height = 16; + sort = 1; + + 3328 = "3D Mode Start"; +} + +starts +{ + color = 1; // Blue + arrow = 1; + title = "Player Starts"; + width = 16; + height = 48; + flags8text = "[8] Spawn on ceiling"; + sprite = "PLAYA0"; + + 1 + { + title = "Player 01 Start"; + sprite = "PLAYA0"; + } + 2 + { + title = "Player 02 Start"; + sprite = "PLAYA0"; + } + 3 + { + title = "Player 03 Start"; + sprite = "PLAYA0"; + } + 4 + { + title = "Player 04 Start"; + sprite = "PLAYA0"; + } + 5 + { + title = "Player 05 Start"; + sprite = "PLAYA0"; + } + 6 + { + title = "Player 06 Start"; + sprite = "PLAYA0"; + } + 7 + { + title = "Player 07 Start"; + sprite = "PLAYA0"; + } + 8 + { + title = "Player 08 Start"; + sprite = "PLAYA0"; + } + 9 + { + title = "Player 09 Start"; + sprite = "PLAYA0"; + } + 10 + { + title = "Player 10 Start"; + sprite = "PLAYA0"; + } + 11 + { + title = "Player 11 Start"; + sprite = "PLAYA0"; + } + 12 + { + title = "Player 12 Start"; + sprite = "PLAYA0"; + } + 13 + { + title = "Player 13 Start"; + sprite = "PLAYA0"; + } + 14 + { + title = "Player 14 Start"; + sprite = "PLAYA0"; + } + 15 + { + title = "Player 15 Start"; + sprite = "PLAYA0"; + } + 16 + { + title = "Player 16 Start"; + sprite = "PLAYA0"; + } + 17 + { + title = "Player 17 Start"; + sprite = "PLAYA0"; + } + 18 + { + title = "Player 18 Start"; + sprite = "PLAYA0"; + } + 19 + { + title = "Player 19 Start"; + sprite = "PLAYA0"; + } + 20 + { + title = "Player 20 Start"; + sprite = "PLAYA0"; + } + 21 + { + title = "Player 21 Start"; + sprite = "PLAYA0"; + } + 22 + { + title = "Player 22 Start"; + sprite = "PLAYA0"; + } + 23 + { + title = "Player 23 Start"; + sprite = "PLAYA0"; + } + 24 + { + title = "Player 24 Start"; + sprite = "PLAYA0"; + } + 25 + { + title = "Player 25 Start"; + sprite = "PLAYA0"; + } + 26 + { + title = "Player 26 Start"; + sprite = "PLAYA0"; + } + 27 + { + title = "Player 27 Start"; + sprite = "PLAYA0"; + } + 28 + { + title = "Player 28 Start"; + sprite = "PLAYA0"; + } + 29 + { + title = "Player 29 Start"; + sprite = "PLAYA0"; + } + 30 + { + title = "Player 30 Start"; + sprite = "PLAYA0"; + } + 31 + { + title = "Player 31 Start"; + sprite = "PLAYA0"; + } + 32 + { + title = "Player 32 Start"; + sprite = "PLAYA0"; + } + 33 + { + title = "Match Start"; + sprite = "NDRNA2A8"; + } + 34 + { + title = "CTF Red Team Start"; + sprite = "SIGNG0"; + } + 35 + { + title = "CTF Blue Team Start"; + sprite = "SIGNE0"; + } +} + +enemies +{ + color = 9; // Light_Blue + arrow = 1; + title = "Enemies"; + + 100 + { + title = "Crawla (Blue)"; + sprite = "POSSA1"; + width = 24; + height = 32; + } + 101 + { + title = "Crawla (Red)"; + sprite = "SPOSA1"; + width = 24; + height = 32; + } + 102 + { + title = "Stupid Dumb Unnamed RoboFish"; + sprite = "FISHA0"; + width = 8; + height = 28; + angletext = "Jump strength"; + } + 103 + { + title = "Buzz (Gold)"; + sprite = "BUZZA1"; + width = 28; + height = 40; + flags8text = "[8] Cannot move"; + } + 104 + { + title = "Buzz (Red)"; + sprite = "RBUZA1"; + width = 28; + height = 40; + flags8text = "[8] Cannot move"; + } + 108 + { + title = "Deton"; + sprite = "DETNA1"; + width = 20; + height = 32; + } + 110 + { + title = "Turret"; + sprite = "TRETA1"; + width = 16; + height = 32; + } + 111 + { + title = "Pop-up Turret"; + sprite = "TURRI1"; + width = 12; + height = 64; + angletext = "Firing delay"; + } + 122 + { + title = "Spring Shell (Green)"; + sprite = "SSHLA1"; + width = 24; + height = 40; + } + 125 + { + title = "Spring Shell (Yellow)"; + sprite = "SSHLI1"; + width = 24; + height = 40; + } + 109 + { + title = "Skim"; + sprite = "SKIMA1"; + width = 16; + height = 24; + } + 113 + { + title = "Jet Jaw"; + sprite = "JJAWA3A7"; + width = 12; + height = 20; + } + 126 + { + title = "Crushstacean"; + sprite = "CRABA0"; + width = 24; + height = 32; + flags8text = "[8] Move left from spawn"; + } + 138 + { + title = "Banpyura"; + sprite = "CR2BA0"; + width = 24; + height = 32; + flags8text = "[8] Move left from spawn"; + } + 117 + { + title = "Robo-Hood"; + sprite = "ARCHA1"; + width = 24; + height = 32; + } + 118 + { + title = "Lance-a-Bot"; + sprite = "CBFSA1"; + width = 32; + height = 72; + } + 1113 + { + title = "Suspicious Lance-a-Bot Statue"; + sprite = "CBBSA1"; + width = 32; + height = 72; + } + 119 + { + title = "Egg Guard"; + sprite = "ESHIA1"; + width = 16; + height = 48; + flags1text = "[1] 90 degrees counter-clockwise"; + flags4text = "[4] 90 degrees clockwise"; + flags8text = "[8] Double speed"; + } + 115 + { + title = "Bird Aircraft Strike Hazard"; + sprite = "VLTRF1"; + width = 12; + height = 24; + } + 120 + { + title = "Green Snapper"; + sprite = "GSNPA1"; + width = 24; + height = 24; + } + 121 + { + title = "Minus"; + sprite = "MNUSA0"; + width = 24; + height = 32; + } + 134 + { + title = "Canarivore"; + sprite = "CANAA0"; + width = 12; + height = 80; + hangs = 1; + } + 123 + { + title = "Unidus"; + sprite = "UNIDA1"; + width = 18; + height = 36; + } + 135 + { + title = "Pterabyte Spawner"; + sprite = "PTERA2A8"; + width = 16; + height = 16; + parametertext = "No. Pterabytes"; + } + 136 + { + title = "Pyre Fly"; + sprite = "PYREA0"; + width = 24; + height = 34; + flags8text = "[8] Start on fire"; + } + 137 + { + title = "Dragonbomber"; + sprite = "DRABA1"; + width = 28; + height = 48; + } + 105 + { + title = "Jetty-Syn Bomber"; + sprite = "JETBB1"; + width = 20; + height = 50; + flags8text = "[8] Cannot move"; + } + 106 + { + title = "Jetty-Syn Gunner"; + sprite = "JETGB1"; + width = 20; + height = 48; + flags8text = "[8] Cannot move"; + } + 112 + { + title = "Spincushion"; + sprite = "SHRPA1"; + width = 16; + height = 24; + } + 114 + { + title = "Snailer"; + sprite = "SNLRA3A7"; + width = 24; + height = 48; + } + 129 + { + title = "Penguinator"; + sprite = "PENGA1"; + width = 24; + height = 32; + } + 130 + { + title = "Pophat"; + sprite = "POPHA1"; + width = 24; + height = 32; + } + 107 + { + title = "Crawla Commander"; + sprite = "CCOMA1"; + width = 16; + height = 32; + } + 131 + { + title = "Spinbobert"; + sprite = "SBOBB0"; + width = 32; + height = 32; + } + 132 + { + title = "Cacolantern"; + sprite = "CACOA0"; + width = 32; + height = 32; + flags8text = "[8] Cannot move"; + } + 133 + { + title = "Hangster"; + sprite = "HBATC1"; + width = 24; + height = 24; + hangs = 1; + } + 127 + { + title = "Hive Elemental"; + sprite = "HIVEA0"; + width = 32; + height = 80; + parametertext = "No. bees"; + } + 128 + { + title = "Bumblebore"; + sprite = "BUMBA1"; + width = 16; + height = 32; + } + 124 + { + title = "Buggle"; + sprite = "BBUZA1"; + width = 20; + height = 24; + } + 116 + { + title = "Pointy"; + sprite = "PNTYA1"; + width = 8; + height = 16; + } +} + +bosses +{ + color = 8; // Dark_Gray + arrow = 1; + title = "Bosses"; + + 200 + { + title = "Egg Mobile"; + sprite = "EGGMA1"; + width = 24; + height = 76; + flags4text = "[4] End level on death"; + flags8text = "[8] Alternate laser attack"; + } + 201 + { + title = "Egg Slimer"; + sprite = "EGGNA1"; + width = 24; + height = 76; + flags4text = "[4] End level on death"; + flags8text = "[8] Speed up when hit"; + } + 202 + { + title = "Sea Egg"; + sprite = "EGGOA1"; + width = 32; + height = 116; + flags4text = "[4] End level on death"; + } + 203 + { + title = "Egg Colosseum"; + sprite = "EGGPA1"; + width = 24; + height = 76; + flags4text = "[4] End level on death"; + } + 204 + { + title = "Fang"; + sprite = "FANGA1"; + width = 24; + height = 60; + flags1text = "[1] Grayscale mode"; + flags4text = "[4] End level on death"; + } + 206 + { + title = "Brak Eggman (Old)"; + sprite = "BRAKB1"; + width = 48; + height = 160; + flags4text = "[4] End level on death"; + } + 207 + { + title = "Metal Sonic (Race)"; + sprite = "METLI1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + } + 208 + { + title = "Metal Sonic (Battle)"; + sprite = "METLC1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + flags4text = "[4] End level on death"; + } + 209 + { + title = "Brak Eggman"; + sprite = "BRAK01"; + width = 48; + height = 160; + flags1text = "[1] No origin-fling death"; + flags4text = "[4] End level on death"; + flags8text = "[8] Electric barrier"; + } + 290 + { + arrow = 0; + title = "Boss Escape Point"; + width = 8; + height = 16; + sprite = "internal:eggmanend"; + } + 291 + { + arrow = 0; + title = "Egg Capsule Center"; + width = 8; + height = 16; + sprite = "internal:capsule"; + } + 292 + { + arrow = 0; + title = "Boss Waypoint"; + width = 8; + height = 16; + flags8text = "[8] Sea Egg shooting point"; + sprite = "internal:eggmanway"; + angletext = "No. (Sea Egg)"; + flagsvaluetext = "No. (Brak)"; + parametertext = "Next"; + } + 293 + { + title = "Metal Sonic Gather Point"; + sprite = "internal:metal"; + width = 8; + height = 16; + } + 294 + { + title = "Fang Waypoint"; + flags8text = "[8] Center waypoint"; + sprite = "internal:eggmanway"; + width = 8; + height = 16; + } +} + +rings +{ + color = 14; // Yellow + title = "Rings and Weapon Panels"; + width = 24; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + sprite = "RINGA0"; + + 300 + { + title = "Ring"; + sprite = "RINGA0"; + width = 16; + } + 301 + { + title = "Bounce Ring"; + sprite = "internal:RNGBA0"; + } + 302 + { + title = "Rail Ring"; + sprite = "internal:RNGRA0"; + } + 303 + { + title = "Infinity Ring"; + sprite = "internal:RNGIA0"; + } + 304 + { + title = "Automatic Ring"; + sprite = "internal:RNGAA0"; + } + 305 + { + title = "Explosion Ring"; + sprite = "internal:RNGEA0"; + } + 306 + { + title = "Scatter Ring"; + sprite = "internal:RNGSA0"; + } + 307 + { + title = "Grenade Ring"; + sprite = "internal:RNGGA0"; + } + 308 + { + title = "CTF Team Ring (Red)"; + sprite = "internal:RRNGA0"; + width = 16; + } + 309 + { + title = "CTF Team Ring (Blue)"; + sprite = "internal:BRNGA0"; + width = 16; + } + 330 + { + title = "Bounce Ring Panel"; + sprite = "internal:PIKBA0"; + } + 331 + { + title = "Rail Ring Panel"; + sprite = "internal:PIKRA0"; + } + 332 + { + title = "Automatic Ring Panel"; + sprite = "internal:PIKAA0"; + } + 333 + { + title = "Explosion Ring Panel"; + sprite = "internal:PIKEA0"; + } + 334 + { + title = "Scatter Ring Panel"; + sprite = "internal:PIKSA0"; + } + 335 + { + title = "Grenade Ring Panel"; + sprite = "internal:PIKGA0"; + } +} + +collectibles +{ + color = 10; // Light_Green + title = "Other Collectibles"; + width = 16; + height = 32; + sort = 1; + sprite = "CEMGA0"; + + 310 + { + title = "CTF Red Flag"; + sprite = "RFLGA0"; + width = 24; + height = 64; + } + 311 + { + title = "CTF Blue Flag"; + sprite = "BFLGA0"; + width = 24; + height = 64; + } + 312 + { + title = "Emerald Token"; + sprite = "TOKEA0"; + width = 16; + height = 32; + flags8height = 24; + flags8text = "[8] Float"; + } + 313 + { + title = "Chaos Emerald 1 (Green)"; + sprite = "CEMGA0"; + } + 314 + { + title = "Chaos Emerald 2 (Purple)"; + sprite = "CEMGB0"; + } + 315 + { + title = "Chaos Emerald 3 (Blue)"; + sprite = "CEMGC0"; + } + 316 + { + title = "Chaos Emerald 4 (Cyan)"; + sprite = "CEMGD0"; + } + 317 + { + title = "Chaos Emerald 5 (Orange)"; + sprite = "CEMGE0"; + } + 318 + { + title = "Chaos Emerald 6 (Red)"; + sprite = "CEMGF0"; + } + 319 + { + title = "Chaos Emerald 7 (Gray)"; + sprite = "CEMGG0"; + } + 320 + { + title = "Emerald Hunt Location"; + sprite = "SHRDA0"; + } + 321 + { + title = "Match Chaos Emerald Spawn"; + sprite = "CEMGA0"; + flags8height = 24; + flags8text = "[8] Float"; + } + 322 + { + title = "Emblem"; + sprite = "EMBMA0"; + width = 16; + height = 30; + flags8height = 24; + flags8text = "[8] Float"; + angletext = "Tag"; + } +} + +boxes +{ + color = 7; // Gray + blocking = 2; + title = "Monitors"; + width = 18; + height = 40; + flags1text = "[1] Run Linedef Executor on pop"; + flags4text = "[4] Random (Strong)"; + flags8text = "[8] Random (Weak)"; + + 400 + { + title = "Super Ring (10 Rings)"; + sprite = "TVRIA0"; + } + 401 + { + title = "Pity Shield"; + sprite = "TVPIA0"; + } + 402 + { + title = "Attraction Shield"; + sprite = "TVATA0"; + } + 403 + { + title = "Force Shield"; + sprite = "TVFOA0"; + } + 404 + { + title = "Armageddon Shield"; + sprite = "TVARA0"; + } + 405 + { + title = "Whirlwind Shield"; + sprite = "TVWWA0"; + } + 406 + { + title = "Elemental Shield"; + sprite = "TVELA0"; + } + 407 + { + title = "Super Sneakers"; + sprite = "TVSSA0"; + } + 408 + { + title = "Invincibility"; + sprite = "TVIVA0"; + } + 409 + { + title = "Extra Life"; + sprite = "TV1UA0"; + flags4text = "[4] Random (Strong) / 10k points"; + flags8text = "[8] Random (Weak) / 10k points"; + } + 410 + { + title = "Eggman"; + sprite = "TVEGA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 411 + { + title = "Teleporter"; + sprite = "TVMXA0"; + } + 413 + { + title = "Gravity Boots"; + sprite = "TVGVA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 414 + { + title = "CTF Team Ring Monitor (Red)"; + sprite = "TRRIA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 415 + { + title = "CTF Team Ring Monitor (Blue)"; + sprite = "TBRIA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 416 + { + title = "Recycler"; + sprite = "TVRCA0"; + } + 418 + { + title = "Score (1,000 Points)"; + sprite = "TV1KA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 419 + { + title = "Score (10,000 Points)"; + sprite = "TVTKA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 420 + { + title = "Flame Shield"; + sprite = "TVFLA0"; + } + 421 + { + title = "Water Shield"; + sprite = "TVBBA0"; + } + 422 + { + title = "Lightning Shield"; + sprite = "TVZPA0"; + } +} + +boxes2 +{ + color = 18; // Gold + blocking = 2; + title = "Monitors (Respawning)"; + width = 20; + height = 44; + flags1text = "[1] Run Linedef Executor on pop"; + + 431 + { + title = "Pity Shield (Respawn)"; + sprite = "TVPIB0"; + } + 432 + { + title = "Attraction Shield (Respawn)"; + sprite = "TVATB0"; + } + 433 + { + title = "Force Shield (Respawn)"; + sprite = "TVFOB0"; + } + 434 + { + title = "Armageddon Shield (Respawn)"; + sprite = "TVARB0"; + } + 435 + { + title = "Whirlwind Shield (Respawn)"; + sprite = "TVWWB0"; + } + 436 + { + title = "Elemental Shield (Respawn)"; + sprite = "TVELB0"; + } + 437 + { + title = "Super Sneakers (Respawn)"; + sprite = "TVSSB0"; + } + 438 + { + title = "Invincibility (Respawn)"; + sprite = "TVIVB0"; + } + 440 + { + title = "Eggman (Respawn)"; + sprite = "TVEGB0"; + } + 443 + { + title = "Gravity Boots (Respawn)"; + sprite = "TVGVB0"; + } + 450 + { + title = "Flame Shield (Respawn)"; + sprite = "TVFLB0"; + } + 451 + { + title = "Water Shield (Respawn)"; + sprite = "TVBBB0"; + } + 452 + { + title = "Lightning Shield (Respawn)"; + sprite = "TVZPB0"; + } +} + +generic +{ + color = 11; // Light_Cyan + title = "Generic Items & Hazards"; + + 500 + { + title = "Air Bubble Patch"; + sprite = "BUBLE0"; + width = 8; + height = 16; + flags8text = "[8] No distance check"; + } + 501 + { + title = "Signpost"; + sprite = "SIGND0"; + width = 8; + height = 32; + } + 502 + { + arrow = 1; + title = "Star Post"; + sprite = "STPTA0M0"; + width = 64; + height = 128; + angletext = "Angle/Order"; + } + 520 + { + title = "Bomb Sphere"; + sprite = "SPHRD0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + unflippable = true; + } + 521 + { + title = "Spikeball"; + sprite = "SPIKA0"; + width = 12; + height = 8; + flags8height = 24; + flags8text = "[8] Float"; + } + 522 + { + title = "Wall Spike"; + sprite = "WSPKALAR"; + width = 16; + height = 14; + flags1text = "[1] Start retracted"; + flags4text = "[4] Retractable"; + flags8text = "[8] Intangible"; + parametertext = "Initial delay"; + } + 523 + { + title = "Spike"; + sprite = "USPKA0"; + width = 8; + height = 32; + flags1text = "[1] Start retracted"; + flags4text = "[4] Retractable"; + flags8text = "[8] Intangible"; + angletext = "Retraction interval"; + parametertext = "Initial delay"; + } + 1130 + { + title = "Small Mace"; + sprite = "SMCEA0"; + width = 17; + height = 34; + } + 1131 + { + title = "Big Mace"; + sprite = "BMCEA0"; + width = 34; + height = 68; + } + 1136 + { + title = "Small Fireball"; + sprite = "SFBRA0"; + width = 17; + height = 34; + } + 1137 + { + title = "Large Fireball"; + sprite = "BFBRA0"; + width = 34; + height = 68; + } +} + +springs +{ + color = 12; // Light_Red + title = "Springs and Fans"; + width = 20; + height = 16; + sprite = "RSPRD2"; + + 540 + { + title = "Fan"; + sprite = "FANSA0D0"; + width = 16; + height = 8; + flags4text = "[4] Invisible"; + flags8text = "[8] No distance check"; + angletext = "Lift height"; + } + 541 + { + title = "Gas Jet"; + sprite = "STEMD0"; + flags8text = "[8] No sounds"; + width = 32; + } + 542 + { + title = "Bumper"; + sprite = "BUMPA0"; + width = 32; + height = 64; + angletext = "Strength"; + } + 543 + { + title = "Balloon"; + sprite = "BLONA0"; + width = 32; + height = 64; + flags8text = "[8] Respawn"; + angletext = "Color"; + } + 550 + { + title = "Yellow Spring"; + sprite = "SPRYA0"; + } + 551 + { + title = "Red Spring"; + sprite = "SPRRA0"; + } + 552 + { + title = "Blue Spring"; + sprite = "SPRBA0"; + } + 555 + { + arrow = 1; + title = "Diagonal Yellow Spring"; + sprite = "YSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 556 + { + arrow = 1; + title = "Diagonal Red Spring"; + sprite = "RSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 557 + { + arrow = 1; + title = "Diagonal Blue Spring"; + sprite = "BSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 558 + { + arrow = 1; + title = "Horizontal Yellow Spring"; + sprite = "SSWYD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 559 + { + arrow = 1; + title = "Horizontal Red Spring"; + sprite = "SSWRD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 560 + { + arrow = 1; + title = "Horizontal Blue Spring"; + sprite = "SSWBD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 1134 + { + title = "Yellow Spring Ball"; + sprite = "YSPBA0"; + width = 17; + height = 34; + } + 1135 + { + title = "Red Spring Ball"; + sprite = "RSPBA0"; + width = 17; + height = 34; + } + 544 + { + arrow = 1; + title = "Yellow Boost Panel"; + sprite = "BSTYA0"; + flags8text = "[8] Force spin"; + width = 28; + height = 2; + } + 545 + { + arrow = 1; + title = "Red Boost Panel"; + sprite = "BSTRA0"; + flags8text = "[8] Force spin"; + width = 28; + height = 2; + } +} + +patterns +{ + color = 5; // Magenta + arrow = 1; + title = "Special Placement Patterns"; + width = 16; + height = 384; + sprite = "RINGA0"; + + 600 + { + arrow = 0; + title = "5 Vertical Rings (Yellow Spring)"; + sprite = "RINGA0"; + } + 601 + { + arrow = 0; + title = "5 Vertical Rings (Red Spring)"; + sprite = "RINGA0"; + height = 1024; + } + 602 + { + title = "5 Diagonal Rings (Yellow Spring)"; + sprite = "RINGA0"; + height = 32; + } + 603 + { + title = "10 Diagonal Rings (Red Spring)"; + sprite = "RINGA0"; + height = 32; + } + 604 + { + title = "Circle of Rings"; + sprite = "RINGA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 605 + { + title = "Circle of Rings (Big)"; + sprite = "RINGA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 606 + { + title = "Circle of Blue Spheres"; + sprite = "SPHRA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 607 + { + title = "Circle of Blue Spheres (Big)"; + sprite = "SPHRA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 608 + { + title = "Circle of Rings and Spheres"; + sprite = "SPHRA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 609 + { + title = "Circle of Rings and Spheres (Big)"; + sprite = "SPHRA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } +} + +invisible +{ + color = 15; // White + title = "Misc. Invisible"; + width = 0; + height = 0; + sprite = "UNKNA0"; + sort = 1; + fixedsize = true; + blocking = 0; + + 700 + { + title = "Water Ambience A (Large)"; + sprite = "internal:ambiance"; + } + + 701 + { + title = "Water Ambience B (Large)"; + sprite = "internal:ambiance"; + } + + 702 + { + title = "Water Ambience C (Medium)"; + sprite = "internal:ambiance"; + } + + 703 + { + title = "Water Ambience D (Medium)"; + sprite = "internal:ambiance"; + } + + 704 + { + title = "Water Ambience E (Small)"; + sprite = "internal:ambiance"; + } + + 705 + { + title = "Water Ambience F (Small)"; + sprite = "internal:ambiance"; + } + + 706 + { + title = "Water Ambience G (Extra Large)"; + sprite = "internal:ambiance"; + } + + 707 + { + title = "Water Ambience H (Extra Large)"; + sprite = "internal:ambiance"; + } + + 708 + { + title = "Disco Ambience"; + sprite = "internal:ambiance"; + } + + 709 + { + title = "Volcano Ambience"; + sprite = "internal:ambiance"; + } + + 710 + { + title = "Machine Ambience"; + sprite = "internal:ambiance"; + } + + 750 + { + title = "Slope Vertex"; + sprite = "internal:vertexslope"; + angletext = "Tag"; + } + + 751 + { + arrow = 1; + title = "Teleport Destination"; + sprite = "internal:tele"; + } + + 752 + { + arrow = 1; + title = "Alternate View Point"; + sprite = "internal:view"; + } + + 753 + { + title = "Zoom Tube Waypoint"; + sprite = "internal:zoom"; + angletext = "Order"; + } + + 754 + { + title = "Push Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Push using XYZ"; + sprite = "GWLGA0"; + angletext = "Radius"; + } + 755 + { + title = "Pull Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Pull using XYZ"; + sprite = "GWLRA0"; + angletext = "Radius"; + } + 756 + { + title = "Blast Linedef Executor"; + sprite = "TOADA0"; + width = 32; + height = 16; + } + 757 + { + title = "Fan Particle Generator"; + sprite = "PRTLA0"; + width = 8; + height = 16; + angletext = "Tag"; + } + 758 + { + title = "Object Angle Anchor"; + sprite = "internal:view"; + } + 760 + { + title = "PolyObject Anchor"; + sprite = "internal:polyanchor"; + angletext = "ID"; + } + + 761 + { + title = "PolyObject Spawn Point"; + sprite = "internal:polycenter"; + angletext = "ID"; + } + + 762 + { + title = "PolyObject Spawn Point (Crush)"; + sprite = "internal:polycentercrush"; + angletext = "ID"; + } + 780 + { + title = "Skybox View Point"; + sprite = "internal:skyb"; + flags4text = "[4] In-map centerpoint"; + parametertext = "ID"; + } +} + +greenflower +{ + color = 10; // Green + title = "Greenflower"; + + 800 + { + title = "GFZ Flower"; + sprite = "FWR1A0"; + width = 16; + height = 40; + } + 801 + { + title = "Sunflower"; + sprite = "FWR2A0"; + width = 16; + height = 96; + } + 802 + { + title = "Budding Flower"; + sprite = "FWR3A0"; + width = 8; + height = 32; + } + 803 + { + title = "Blueberry Bush"; + sprite = "BUS3A0"; + width = 16; + height = 32; + } + 804 + { + title = "Berry Bush"; + sprite = "BUS1A0"; + width = 16; + height = 32; + } + 805 + { + title = "Bush"; + sprite = "BUS2A0"; + width = 16; + height = 32; + } + 806 + { + title = "GFZ Tree"; + sprite = "TRE1A0"; + width = 20; + height = 128; + } + 807 + { + title = "GFZ Berry Tree"; + sprite = "TRE1B0"; + width = 20; + height = 128; + } + 808 + { + title = "GFZ Cherry Tree"; + sprite = "TRE1C0"; + width = 20; + height = 128; + } + 809 + { + title = "Checkered Tree"; + sprite = "TRE2A0"; + width = 20; + height = 200; + } + 810 + { + title = "Checkered Tree (Sunset)"; + sprite = "TRE2B0"; + width = 20; + height = 200; + } + 811 + { + title = "Polygon Tree"; + sprite = "TRE4A0"; + width = 20; + height = 200; + } + 812 + { + title = "Bush Tree"; + sprite = "TRE5A0"; + width = 20; + height = 200; + } + 813 + { + title = "Red Bush Tree"; + sprite = "TRE5B0"; + width = 20; + height = 200; + } +} + +technohill +{ + color = 10; // Green + title = "Techno Hill"; + + 900 + { + title = "THZ Steam Flower"; + sprite = "THZPA0"; + width = 8; + height = 32; + } + 901 + { + title = "Alarm"; + sprite = "ALRMA0"; + width = 8; + height = 16; + hangs = 1; + } + 902 + { + title = "THZ Spin Flower (Red)"; + sprite = "FWR5A0"; + width = 16; + height = 64; + } + 903 + { + title = "THZ Spin Flower (Yellow)"; + sprite = "FWR6A0"; + width = 16; + height = 64; + } + 904 + { + arrow = 1; + title = "Whistlebush"; + sprite = "THZTA0"; + width = 16; + height = 64; + } +} + +deepsea +{ + color = 10; // Green + title = "Deep Sea"; + + 1000 + { + arrow = 1; + blocking = 2; + title = "Gargoyle"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1009 + { + arrow = 1; + blocking = 2; + title = "Gargoyle (Big)"; + sprite = "GARGB1"; + width = 32; + height = 80; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1001 + { + title = "Seaweed"; + sprite = "SEWEA0"; + width = 24; + height = 56; + } + 1002 + { + title = "Dripping Water"; + sprite = "DRIPD0"; + width = 8; + height = 16; + hangs = 1; + angletext = "Dripping interval"; + } + 1003 + { + title = "Coral (Green)"; + sprite = "CORLA0"; + width = 29; + height = 40; + } + 1004 + { + title = "Coral (Red)"; + sprite = "CORLB0"; + width = 30; + height = 53; + } + 1005 + { + title = "Coral (Orange)"; + sprite = "CORLC0"; + width = 28; + height = 41; + } + 1006 + { + title = "Blue Crystal"; + sprite = "BCRYA1"; + width = 8; + height = 16; + } + 1007 + { + title = "Kelp"; + sprite = "KELPA0"; + width = 16; + height = 292; + flags4text = "[4] Double size"; + } + 1008 + { + title = "Stalagmite (DSZ1)"; + sprite = "DSTGA0"; + width = 8; + height = 116; + flags4text = "[4] Double size"; + } + 1010 + { + arrow = 1; + title = "Light Beam"; + sprite = "LIBEARAL"; + width = 16; + height = 16; + } + 1011 + { + title = "Stalagmite (DSZ2)"; + sprite = "DSTGA0"; + width = 8; + height = 116; + flags4text = "[4] Double size"; + } + 1012 + { + arrow = 1; + title = "Big Floating Mine"; + width = 28; + height = 56; + sprite = "BMNEA1"; + } + 1013 + { + title = "Animated Kelp"; + sprite = "ALGAA0"; + width = 48; + height = 120; + } + 1014 + { + title = "Large Coral (Brown)"; + sprite = "CORLD0"; + width = 56; + height = 112; + } + 1015 + { + title = "Large Coral (Beige)"; + sprite = "CORLE0"; + width = 56; + height = 112; + } +} + +castleeggman +{ + color = 10; // Green + title = "Castle Eggman"; + + 1100 + { + title = "Chain (Decorative)"; + sprite = "CHANA0"; + width = 4; + height = 128; + hangs = 1; + } + 1101 + { + title = "Torch"; + sprite = "FLAMA0E0"; + width = 8; + height = 32; + flags1text = "[1] Add corona"; + } + 1102 + { + arrow = 1; + blocking = 2; + title = "Eggman Statue"; + sprite = "ESTAA1"; + width = 32; + height = 240; + flags1text = "[1] Solid gold"; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1103 + { + title = "CEZ Flower"; + sprite = "FWR4A0"; + width = 16; + height = 40; + } + 1104 + { + title = "Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1105 + { + title = "Chain with Maces Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1106 + { + title = "Chained Spring Spawnpoint"; + sprite = "YSPBA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Red spring"; + angletext = "Tag"; + } + 1107 + { + title = "Chain Spawnpoint"; + sprite = "BMCHA0"; + width = 17; + height = 34; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1108 + { + arrow = 1; + title = "Hidden Chain Spawnpoint"; + sprite = "internal:chain3"; + width = 17; + height = 34; + flags8text = "[8] Double size"; + } + 1109 + { + title = "Firebar Spawnpoint"; + sprite = "BFBRA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1110 + { + title = "Custom Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + angletext = "Tag"; + } + 1111 + { + arrow = 1; + blocking = 2; + title = "Crawla Statue"; + sprite = "CSTAA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1112 + { + arrow = 1; + blocking = 2; + title = "Lance-a-Bot Statue"; + sprite = "CBBSA1"; + width = 32; + height = 72; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1114 + { + title = "Pine Tree"; + sprite = "PINEA0"; + width = 16; + height = 628; + } + 1115 + { + title = "CEZ Shrub (Small)"; + sprite = "CEZBA0"; + width = 16; + height = 24; + } + 1116 + { + title = "CEZ Shrub (Large)"; + sprite = "CEZBB0"; + width = 32; + height = 48; + } + 1117 + { + arrow = 1; + title = "Pole Banner (Red)"; + sprite = "BANRA0"; + width = 40; + height = 224; + } + 1118 + { + arrow = 1; + title = "Pole Banner (Blue)"; + sprite = "BANRA0"; + width = 40; + height = 224; + } + 1119 + { + title = "Candle"; + sprite = "CNDLA0"; + width = 8; + height = 48; + flags1text = "[1] Add corona"; + } + 1120 + { + title = "Candle Pricket"; + sprite = "CNDLB0"; + width = 8; + height = 176; + flags1text = "[1] Add corona"; + } + 1121 + { + title = "Flame Holder"; + sprite = "FLMHA0"; + width = 24; + height = 80; + flags1text = "[1] Add corona"; + flags4text = "[4] No flame"; + } + 1122 + { + title = "Fire Torch"; + sprite = "CTRCA0"; + width = 16; + height = 80; + } + 1123 + { + title = "Cannonball Launcher"; + sprite = "internal:cannonball"; + width = 8; + height = 16; + } + 1124 + { + blocking = 2; + title = "Cannonball"; + sprite = "CBLLA0"; + width = 20; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1125 + { + title = "Brambles"; + sprite = "CABRALAR"; + width = 48; + height = 32; + } + 1126 + { + title = "Invisible Lockon Object"; + sprite = "LCKNC0"; + width = 16; + height = 32; + } + 1127 + { + title = "Spectator Eggrobo"; + sprite = "EGR1A1"; + width = 20; + height = 72; + } + 1128 + { + arrow = 1; + title = "Waving Flag (Red)"; + sprite = "CFLGA0"; + width = 8; + height = 208; + } + 1129 + { + arrow = 1; + title = "Waving Flag (Blue)"; + sprite = "CFLGA0"; + width = 8; + height = 208; + } +} + +aridcanyon +{ + color = 10; // Green + title = "Arid Canyon"; + + 1200 + { + title = "Tumbleweed (Big)"; + sprite = "BTBLA0"; + width = 24; + height = 48; + flags8text = "[8] Moves perpetually"; + } + 1201 + { + title = "Tumbleweed (Small)"; + sprite = "STBLA0"; + width = 12; + height = 24; + flags8text = "[8] Moves perpetually"; + } + 1202 + { + arrow = 1; + title = "Rock Spawner"; + sprite = "ROIAA0"; + width = 8; + height = 16; + angletext = "Tag"; + } + 1203 + { + title = "Tiny Red Flower Cactus"; + sprite = "CACTA0"; + width = 13; + height = 24; + } + 1204 + { + title = "Small Red Flower Cactus"; + sprite = "CACTB0"; + width = 15; + height = 52; + } + 1205 + { + title = "Tiny Blue Flower Cactus"; + sprite = "CACTC0"; + width = 13; + height = 24; + } + 1206 + { + title = "Small Blue Flower Cactus"; + sprite = "CACTD0"; + width = 15; + height = 52; + } + 1207 + { + title = "Prickly Pear"; + sprite = "CACTE0"; + width = 32; + height = 96; + } + 1208 + { + title = "Barrel Cactus"; + sprite = "CACTF0"; + width = 20; + height = 128; + } + 1209 + { + title = "Tall Barrel Cactus"; + sprite = "CACTG0"; + width = 24; + height = 224; + } + 1210 + { + title = "Armed Cactus"; + sprite = "CACTH0"; + width = 24; + height = 256; + } + 1211 + { + title = "Ball Cactus"; + sprite = "CACTI0"; + width = 48; + height = 96; + } + 1212 + { + title = "Caution Sign"; + sprite = "WWSGAR"; + width = 22; + height = 64; + } + 1213 + { + title = "Cacti Sign"; + sprite = "WWS2AR"; + width = 22; + height = 64; + } + 1214 + { + title = "Sharp Turn Sign"; + sprite = "WWS3ALAR"; + width = 16; + height = 192; + } + 1215 + { + title = "Mine Oil Lamp"; + sprite = "OILLA0"; + width = 22; + height = 64; + hangs = 1; + } + 1216 + { + title = "TNT Barrel"; + sprite = "BARRA1"; + width = 24; + height = 63; + } + 1217 + { + title = "TNT Proximity Shell"; + sprite = "REMTA0"; + width = 64; + height = 40; + } + 1218 + { + title = "Dust Devil"; + sprite = "TAZDCR"; + width = 80; + height = 416; + } + 1219 + { + title = "Minecart Spawner"; + sprite = "MCRTCLFR"; + width = 22; + height = 32; + } + 1220 + { + title = "Minecart Stopper"; + sprite = "MCRTIR"; + width = 32; + height = 32; + } + 1221 + { + title = "Minecart Saloon Door"; + sprite = "SALDARAL"; + width = 96; + height = 160; + flags8text = "[8] Allow non-minecart players"; + } + 1222 + { + title = "Train Cameo Spawner"; + sprite = "TRAEBRBL"; + width = 28; + height = 32; + } + 1223 + { + title = "Train Dust Spawner"; + sprite = "ADSTA0"; + width = 4; + height = 4; + } + 1224 + { + title = "Train Steam Spawner"; + sprite = "STEAA0"; + width = 4; + height = 4; + } + 1229 + { + title = "Minecart Switch Point"; + sprite = "internal:zoom"; + width = 8; + height = 16; + flags8text = "[8] Enable switching"; + } + 1230 + { + title = "Tiny Cactus"; + sprite = "CACTJ0"; + width = 13; + height = 28; + } + 1231 + { + title = "Small Cactus"; + sprite = "CACTK0"; + width = 15; + height = 60; + } +} + +redvolcano +{ + color = 10; // Green + title = "Red Volcano"; + + 1300 + { + arrow = 1; + title = "Flame Jet (Horizontal)"; + sprite = "internal:flameh"; + width = 16; + height = 40; + flags8text = "[8] Waves vertically"; + angletext = "On/Off time"; + parametertext = "Strength"; + } + 1301 + { + title = "Flame Jet (Vertical)"; + sprite = "internal:flamev"; + width = 16; + height = 40; + flags8text = "[8] Shoot downwards"; + angletext = "On/Off time"; + parametertext = "Strength"; + } + 1302 + { + title = "Spinning Flame Jet (Counter-Clockwise)"; + sprite = "internal:flame2"; + width = 16; + height = 24; + } + 1303 + { + title = "Spinning Flame Jet (Clockwise)"; + sprite = "internal:flame1"; + width = 16; + height = 24; + } + 1304 + { + title = "Lavafall"; + sprite = "LFALF0"; + width = 30; + height = 32; + angletext = "Initial delay"; + flags8text = "[8] Double size"; + } + 1305 + { + title = "Rollout Rock"; + sprite = "PUMIA1A5"; + width = 30; + height = 60; + flags8text = "[8] Non-buoyant"; + } + 1306 + { + title = "Big Fern"; + sprite = "JPLAB0"; + width = 32; + height = 48; + } + 1307 + { + title = "Jungle Palm"; + sprite = "JPLAC0"; + width = 32; + height = 48; + } + 1308 + { + title = "Torch Flower"; + sprite = "TFLOA0"; + width = 14; + height = 110; + } + 1309 + { + title = "RVZ1 Wall Vine (Long)"; + sprite = "WVINALAR"; + width = 1; + height = 288; + } + 1310 + { + title = "RVZ1 Wall Vine (Short)"; + sprite = "WVINBLBR"; + width = 1; + height = 288; + } +} + +botanicserenity +{ + color = 10; // Green + title = "Botanic Serenity"; + width = 16; + height = 32; + sprite = "BSZ1A0"; + 1400 + { + title = "Tall Flower (Red)"; + sprite = "BSZ1A0"; + } + 1401 + { + title = "Tall Flower (Purple)"; + sprite = "BSZ1B0"; + } + 1402 + { + title = "Tall Flower (Blue)"; + sprite = "BSZ1C0"; + } + 1403 + { + title = "Tall Flower (Cyan)"; + sprite = "BSZ1D0"; + } + 1404 + { + title = "Tall Flower (Yellow)"; + sprite = "BSZ1E0"; + } + 1405 + { + title = "Tall Flower (Orange)"; + sprite = "BSZ1F0"; + } + 1410 + { + title = "Medium Flower (Red)"; + sprite = "BSZ2A0"; + } + 1411 + { + title = "Medium Flower (Purple)"; + sprite = "BSZ2B0"; + } + 1412 + { + title = "Medium Flower (Blue)"; + sprite = "BSZ2C0"; + } + 1413 + { + title = "Medium Flower (Cyan)"; + sprite = "BSZ2D0"; + } + 1414 + { + title = "Medium Flower (Yellow)"; + sprite = "BSZ2E0"; + } + 1415 + { + title = "Medium Flower (Orange)"; + sprite = "BSZ2F0"; + } + 1420 + { + title = "Short Flower (Red)"; + sprite = "BSZ3A0"; + } + 1421 + { + title = "Short Flower (Purple)"; + sprite = "BSZ3B0"; + } + 1422 + { + title = "Short Flower (Blue)"; + sprite = "BSZ3C0"; + } + 1423 + { + title = "Short Flower (Cyan)"; + sprite = "BSZ3D0"; + } + 1424 + { + title = "Short Flower (Yellow)"; + sprite = "BSZ3E0"; + } + 1425 + { + title = "Short Flower (Orange)"; + sprite = "BSZ3F0"; + } + 1430 + { + title = "Tulip (Red)"; + sprite = "BST1A0"; + } + 1431 + { + title = "Tulip (Purple)"; + sprite = "BST2A0"; + } + 1432 + { + title = "Tulip (Blue)"; + sprite = "BST3A0"; + } + 1433 + { + title = "Tulip (Cyan)"; + sprite = "BST4A0"; + } + 1434 + { + title = "Tulip (Yellow)"; + sprite = "BST5A0"; + } + 1435 + { + title = "Tulip (Orange)"; + sprite = "BST6A0"; + } + 1440 + { + title = "Cluster (Red)"; + sprite = "BSZ5A0"; + } + 1441 + { + title = "Cluster (Purple)"; + sprite = "BSZ5B0"; + } + 1442 + { + title = "Cluster (Blue)"; + sprite = "BSZ5C0"; + } + 1443 + { + title = "Cluster (Cyan)"; + sprite = "BSZ5D0"; + } + 1444 + { + title = "Cluster (Yellow)"; + sprite = "BSZ5E0"; + } + 1445 + { + title = "Cluster (Orange)"; + sprite = "BSZ5F0"; + } + 1450 + { + title = "Bush (Red)"; + sprite = "BSZ6A0"; + } + 1451 + { + title = "Bush (Purple)"; + sprite = "BSZ6B0"; + } + 1452 + { + title = "Bush (Blue)"; + sprite = "BSZ6C0"; + } + 1453 + { + title = "Bush (Cyan)"; + sprite = "BSZ6D0"; + } + 1454 + { + title = "Bush (Yellow)"; + sprite = "BSZ6E0"; + } + 1455 + { + title = "Bush (Orange)"; + sprite = "BSZ6F0"; + } + 1460 + { + title = "Vine (Red)"; + sprite = "BSZ7A0"; + } + 1461 + { + title = "Vine (Purple)"; + sprite = "BSZ7B0"; + } + 1462 + { + title = "Vine (Blue)"; + sprite = "BSZ7C0"; + } + 1463 + { + title = "Vine (Cyan)"; + sprite = "BSZ7D0"; + } + 1464 + { + title = "Vine (Yellow)"; + sprite = "BSZ7E0"; + } + 1465 + { + title = "Vine (Orange)"; + sprite = "BSZ7F0"; + } + 1470 + { + title = "BSZ Shrub"; + sprite = "BSZ8A0"; + } + 1471 + { + title = "BSZ Clover"; + sprite = "BSZ8B0"; + } + 1473 + { + title = "Palm Tree (Big)"; + width = 16; + height = 160; + sprite = "BSZ8D0"; + } + 1475 + { + title = "Palm Tree (Small)"; + width = 16; + height = 80; + sprite = "BSZ8F0"; + } +} + +azuretemple +{ + color = 10; // Green + title = "Azure Temple"; + + 1500 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1501 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Up)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1502 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Down)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1503 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Long)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1504 + { + title = "ATZ Target"; + sprite = "RCRYB0"; + width = 24; + height = 32; + } + 1505 + { + title = "Green Flame"; + sprite = "CFLMA0E0"; + width = 8; + height = 32; + } + 1506 + { + arrow = 1; + blocking = 2; + title = "Blue Gargoyle"; + sprite = "BGARD1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } +} + +dreamhill +{ + color = 10; // Green + title = "Dream Hill"; + + 1600 + { + title = "Spring Tree"; + sprite = "TRE6A0"; + width = 16; + height = 32; + } + 1601 + { + title = "Shleep"; + sprite = "SHLPA0"; + width = 24; + height = 32; + } + 1602 + { + title = "Pian"; + sprite = "NTPNALAR"; + width = 16; + height = 32; + } +} + +nightstrk +{ + color = 13; // Pink + title = "NiGHTS Track"; + width = 8; + height = 4096; + sprite = "UNKNA0"; + + 1700 + { + title = "Axis"; + sprite = "internal:axis1"; + circle = 1; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + angletext = "Radius/Direction"; + parametertext = "Mare"; + } + 1701 + { + title = "Axis Transfer"; + sprite = "internal:axis2"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1702 + { + title = "Axis Transfer Line"; + sprite = "internal:axis3"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1710 + { + title = "Ideya Capture"; + sprite = "CAPSA0"; + width = 72; + height = 144; + angletext = "Rings"; + parametertext = "Mare"; + } +} + +nights +{ + color = 13; // Pink + title = "NiGHTS Items"; + width = 16; + height = 32; + + 1703 + { + title = "Ideya Drone"; + sprite = "NDRNA1"; + width = 16; + height = 56; + flags1text = "[1] Align player to middle"; + flags4text = "[4] Align player to top"; + flags8text = "[8] Die upon time up"; + angletext = "Time limit"; + parametertext = "Height"; + } + 1704 + { + arrow = 1; + title = "NiGHTS Bumper"; + sprite = "NBMPG3G7"; + width = 32; + height = 64; + unflippable = true; + flagsvaluetext = "Pitch"; + angletext = "Yaw"; + } + 1705 + { + arrow = 1; + title = "Hoop (Generic)"; + sprite = "HOOPA0"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + flagsvaluetext = "Height"; + angletext = "Pitch/Yaw"; + } + 1706 + { + title = "Blue Sphere"; + sprite = "SPHRA0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + unflippable = true; + } + 1707 + { + title = "Super Paraloop"; + sprite = "NPRUA0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1708 + { + title = "Drill Refill"; + sprite = "NPRUB0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1709 + { + title = "Nightopian Helper"; + sprite = "NPRUC0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1711 + { + title = "Extra Time"; + sprite = "NPRUD0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1712 + { + title = "Link Freeze"; + sprite = "NPRUE0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1713 + { + arrow = 1; + title = "Hoop (Customizable)"; + flags1text = "[1] Radius +16"; + flags2text = "[2] Radius +32"; + flags4text = "[4] Radius +64"; + flags8text = "[8] Radius +128"; + sprite = "HOOPA0"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + } + 1714 + { + title = "Ideya Anchor Point"; + sprite = "internal:axis1"; + width = 8; + height = 16; + parametertext = "Ideya"; + } +} + +mario +{ + color = 6; // Brown + title = "Mario"; + + 1800 + { + title = "Coin"; + sprite = "COINA0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + } + 1801 + { + arrow = 1; + title = "Goomba"; + sprite = "GOOMA0"; + width = 24; + height = 32; + } + 1802 + { + arrow = 1; + title = "Goomba (Blue)"; + sprite = "BGOMA0"; + width = 24; + height = 32; + } + 1803 + { + title = "Fire Flower"; + sprite = "FFWRB0"; + width = 16; + height = 32; + } + 1804 + { + title = "Koopa Shell"; + sprite = "SHLLA1"; + width = 16; + height = 20; + } + 1805 + { + title = "Puma (Jumping Fireball)"; + sprite = "PUMAA0"; + width = 8; + height = 16; + angletext = "Jump strength"; + } + 1806 + { + title = "King Bowser"; + sprite = "KOOPA0"; + width = 16; + height = 48; + } + 1807 + { + title = "Axe"; + sprite = "MAXEA0"; + width = 8; + height = 16; + } + 1808 + { + title = "Bush (Short)"; + sprite = "MUS1A0"; + width = 16; + height = 32; + } + 1809 + { + title = "Bush (Tall)"; + sprite = "MUS2A0"; + width = 16; + height = 32; + } + 1810 + { + title = "Toad"; + sprite = "TOADA0"; + width = 8; + height = 32; + } +} + +christmasdisco +{ + color = 10; // Green + title = "Christmas & Disco"; + + 1850 + { + title = "Christmas Pole"; + sprite = "XMS1A0"; + width = 16; + height = 40; + } + 1851 + { + title = "Candy Cane"; + sprite = "XMS2A0"; + width = 8; + height = 32; + } + 1852 + { + blocking = 2; + title = "Snowman"; + sprite = "XMS3A0"; + width = 16; + height = 64; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1853 + { + blocking = 2; + title = "Snowman (With Hat)"; + sprite = "XMS3B0"; + width = 16; + height = 80; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1854 + { + title = "Lamp Post"; + sprite = "XMS4A0"; + width = 8; + height = 120; + } + 1855 + { + title = "Lamp Post (Snow)"; + sprite = "XMS4B0"; + width = 8; + height = 120; + } + 1856 + { + title = "Hanging Star"; + sprite = "XMS5A0"; + width = 4; + height = 80; + hangs = 1; + } + 1857 + { + title = "Berry Bush (Snow)"; + sprite = "BUS1B0"; + width = 16; + height = 32; + } + 1858 + { + title = "Bush (Snow)"; + sprite = "BUS2B0"; + width = 16; + height = 32; + } + 1859 + { + title = "Blueberry Bush (Snow)"; + sprite = "BUS3B0"; + width = 16; + height = 32; + } + 1875 + { + title = "Disco Ball"; + sprite = "DBALA0"; + width = 16; + height = 54; + hangs = 1; + } + 1876 + { + arrow = 1; + blocking = 2; + title = "Eggman Disco Statue"; + sprite = "ESTAB1"; + width = 20; + height = 96; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } +} + +stalagmites +{ + color = 10; // Green + title = "Stalagmites"; + width = 16; + height = 40; + + 1900 + { + title = "Brown Stalagmite (Tall)"; + sprite = "STLGA0"; + width = 16; + height = 40; + } + 1901 + { + title = "Brown Stalagmite"; + sprite = "STLGB0"; + width = 16; + height = 40; + } + 1902 + { + title = "Orange Stalagmite (Tall)"; + sprite = "STLGC0"; + width = 16; + height = 40; + } + 1903 + { + title = "Orange Stalagmite"; + sprite = "STLGD0"; + width = 16; + height = 40; + } + 1904 + { + title = "Red Stalagmite (Tall)"; + sprite = "STLGE0"; + width = 16; + height = 40; + } + 1905 + { + title = "Red Stalagmite"; + sprite = "STLGF0"; + width = 16; + height = 40; + } + 1906 + { + title = "Gray Stalagmite (Tall)"; + sprite = "STLGG0"; + width = 24; + height = 96; + } + 1907 + { + title = "Gray Stalagmite"; + sprite = "STLGH0"; + width = 16; + height = 40; + } + 1908 + { + title = "Blue Stalagmite (Tall)"; + sprite = "STLGI0"; + width = 16; + height = 40; + } + 1909 + { + title = "Blue Stalagmite"; + sprite = "STLGJ0"; + width = 16; + height = 40; + } +} + +hauntedheights +{ + color = 10; // Green + title = "Haunted Heights"; + + 2000 + { + title = "Smashing Spikeball"; + sprite = "FMCEA0"; + width = 18; + height = 28; + angletext = "Initial delay"; + } + 2001 + { + title = "HHZ Grass"; + sprite = "HHZMA0"; + width = 16; + height = 40; + } + 2002 + { + title = "HHZ Tentacle 1"; + sprite = "HHZMB0"; + width = 16; + height = 40; + } + 2003 + { + title = "HHZ Tentacle 2"; + sprite = "HHZMC0"; + width = 16; + height = 40; + } + 2004 + { + title = "HHZ Stalagmite (Tall)"; + sprite = "HHZME0"; + width = 16; + height = 40; + } + 2005 + { + title = "HHZ Stalagmite (Short)"; + sprite = "HHZMF0"; + width = 16; + height = 40; + } + 2006 + { + title = "Jack-o'-lantern 1"; + sprite = "PUMKA0"; + width = 16; + height = 40; + flags1text = "Don't flicker"; + } + 2007 + { + title = "Jack-o'-lantern 2"; + sprite = "PUMKB0"; + width = 16; + height = 40; + flags1text = "Don't flicker"; + } + 2008 + { + title = "Jack-o'-lantern 3"; + sprite = "PUMKC0"; + width = 16; + height = 40; + flags1text = "Don't flicker"; + } + 2009 + { + title = "Purple Mushroom"; + sprite = "SHRMD0"; + width = 16; + height = 48; + } + 2010 + { + title = "HHZ Tree"; + sprite = "HHPLC0"; + width = 12; + height = 40; + } +} + +frozenhillside +{ + color = 10; // Green + title = "Frozen Hillside"; + + 2100 + { + title = "Ice Shard (Small)"; + sprite = "FHZIA0"; + width = 8; + height = 32; + } + 2101 + { + title = "Ice Shard (Large)"; + sprite = "FHZIB0"; + width = 8; + height = 32; + } + 2102 + { + title = "Crystal Tree (Aqua)"; + sprite = "TRE3A0"; + width = 20; + height = 200; + } + 2103 + { + title = "Crystal Tree (Pink)"; + sprite = "TRE3B0"; + width = 20; + height = 200; + } + 2104 + { + title = "Amy Cameo"; + sprite = "ROSYA1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + } + 2105 + { + title = "Mistletoe"; + sprite = "XMS6A0"; + width = 52; + height = 106; + } +} + +flickies +{ + color = 10; // Green + title = "Flickies"; + width = 8; + height = 20; + flags1text = "[1] Move aimlessly"; + flags4text = "[4] No movement"; + flags8text = "[8] Hop"; + angletext = "Radius"; + + 2200 + { + title = "Bluebird"; + sprite = "FL01A1"; + } + 2201 + { + title = "Rabbit"; + sprite = "FL02A1"; + } + 2202 + { + title = "Chicken"; + sprite = "FL03A1"; + } + 2203 + { + title = "Seal"; + sprite = "FL04A1"; + } + 2204 + { + title = "Pig"; + sprite = "FL05A1"; + } + 2205 + { + title = "Chipmunk"; + sprite = "FL06A1"; + } + 2206 + { + title = "Penguin"; + sprite = "FL07A1"; + } + 2207 + { + title = "Fish"; + sprite = "FL08A1"; + parametertext = "Color"; + } + 2208 + { + title = "Ram"; + sprite = "FL09A1"; + } + 2209 + { + title = "Puffin"; + sprite = "FL10A1"; + } + 2210 + { + title = "Cow"; + sprite = "FL11A1"; + } + 2211 + { + title = "Rat"; + sprite = "FL12A1"; + } + 2212 + { + title = "Bear"; + sprite = "FL13A1"; + } + 2213 + { + title = "Dove"; + sprite = "FL14A1"; + } + 2214 + { + title = "Cat"; + sprite = "FL15A1"; + } + 2215 + { + title = "Canary"; + sprite = "FL16A1"; + } + 2216 + { + title = "Spider"; + sprite = "FS01A1"; + } + 2217 + { + title = "Bat"; + sprite = "FS02A0"; + } +} \ No newline at end of file diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg deleted file mode 100644 index 5bc48211c..000000000 --- a/extras/conf/SRB2-22.cfg +++ /dev/null @@ -1,6521 +0,0 @@ -/*********************************************************\ - Zone Builder Game Configuration - For Sonic Robo Blast 2 Version 2.2 - Contributors (alphabetical): - * Foxboy - * FuriousFox - * JJames19119 - * Kalaron - * Kristos - * MascaraSnake - * mazmazz - * Morpheus - * Neo Chaotikal - * Nev3r - * Oogaland - * Rob - * Shadow Hog - * Spherallic - * SRB2-Playah - * SSNTails - * SteelT - * ST218 - * toaster - * Viola -\*********************************************************/ - -// This is required to prevent accidental use of a different configuration -type = "Doom Builder 2 Game Configuration"; - -// This is the title to show for this game -game = "Sonic Robo Blast 2 - 2.2"; - -//GZDB specific. Don't try to load lumps that don't exist. -basegame = 0; - -// This is the simplified game engine/sourceport name -engine = "zdoom"; - -// When this is set to true, sectors with the same tag will light up when a line is highlighted -linetagindicatesectors = true; - -// The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder -formatinterface = "SRB2MapSetIO"; - -//Sky textures for vanilla maps -defaultskytextures -{ - SKY1 = "MAP01,MAP02,MAP03,MAP33,MAP50,MAP60,MAPF0,MAPM0"; - SKY2 = "MAPM7,MAPMB"; - SKY4 = "MAP04,MAP06,MAP61,MAPF6,MAPM1"; - SKY6 = "MAP05,MAP51,MAPMA"; - SKY7 = "MAPM2,MAPM5"; - SKY8 = "MAP07,MAP08,MAP09,MAP52,MAP62,MAPF1"; - SKY10 = "MAP10,MAP12,MAP53,MAP63,MAPM3"; - SKY11 = "MAP11,MAPF7"; - SKY13 = "MAP13,MAP64"; - SKY14 = "MAP14"; - SKY15 = "MAP15,MAP54"; - SKY17 = "MAP70"; - SKY20 = "MAP32,MAP55,MAP65,MAPF2,MAPF5"; - SKY21 = "MAPM4"; - SKY22 = "MAP22,MAP23,MAP25,MAP26,MAP27,MAP56,MAP66,MAPF4,MAPM6"; - SKY30 = "MAP30"; - SKY31 = "MAP31"; - SKY35 = "MAP42"; - SKY40 = "MAP41,MAP71,MAPM9"; - SKY55 = "MAPF3,MAPM8"; - SKY68 = "MAPF8"; - SKY99 = "MAP57,MAPZ0"; - SKY159 = "MAP16"; - SKY172 = "MAP40"; - SKY300 = "MAP72"; - SKY301 = "MAP73"; -} - -// Default lump name for new map -defaultlumpname = "MAP01"; - -// Default testing parameters -testparameters = "-file \"%AP\" \"%F\" -warp %L"; -testshortpaths = true; - -// Default nodebuilder configurations -defaultsavecompiler = "zennode_normal"; -defaulttestcompiler = "zennode_fast"; - -// Skill levels -skills -{ - 1 = "Normal"; -} - -// Skins -skins -{ - Sonic; - Tails; - Knuckles; - Amy; - Fang; - Metalsonic; -} - -// Gametypes -gametypes -{ - -1 = "Single Player"; - 0 = "Co-op"; - 1 = "Competition"; - 2 = "Race"; - 3 = "Match"; - 4 = "Team Match"; - 5 = "Tag"; - 6 = "Hide and Seek"; - 7 = "CTF"; -} - -// Special linedefs -soundlinedefflag = 64; // See linedefflags -singlesidedflag = 1; // See linedefflags -doublesidedflag = 4; // See linedefflags -impassableflag = 1; -upperunpeggedflag = 8; -lowerunpeggedflag = 16; -repeatmidtextureflag = 1024; -pegmidtextureflag = 256; - -// Generalized actions -generalizedlinedefs = false; -generalizedsectors = true; - -// Texture loading options -defaultwalltexture = "GFZROCK"; -defaultfloortexture = "GFZFLR01"; -defaultceilingtexture = "F_SKY1"; -mixtexturesflats = true; -defaulttexturescale = 1.0f; -defaultflatscale = 1.0f; - -// Thing number for start position in 3D Mode -start3dmode = 3328; - - - - -/* -TEXTURES AND FLAT SOURCES -This tells Doom Builder where to find the information for textures -and flats in the IWAD file, Addition WAD file and Map WAD file. - -Start and end lumps must be given in a structure (of which the -key name doesnt matter) and any textures or flats in between them -are loaded in either the textures category or flats category. - -For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. -Kalaron: and now TX_START -*/ - -// Texture sources -textures -{ - zdoom1 - { - start = "TX_START"; - end = "TX_END"; - } -} - -// Patch sources -patches -{ - standard1 - { - start = "P_START"; - end = "P_END"; - } - - standard2 - { - start = "PP_START"; - end = "PP_END"; - } -} - -// Sprite sources -sprites -{ - standard1 - { - start = "S_START"; - end = "S_END"; - } - - standard2 - { - start = "SS_START"; - end = "SS_END"; - } -} - -// Flat sources -flats -{ - standard1 - { - start = "F_START"; - end = "F_END"; - } - - standard2 - { - start = "FF_START"; - end = "FF_END"; - } - - standard3 - { - start = "FF_START"; - end = "F_END"; - } - - standard4 - { - start = "F_START"; - end = "FF_END"; - } -} - - -/* -GAME DETECT PATTERN -Used to guess the game for which a WAD file is made. - -1 = One of these lumps must exist -2 = None of these lumps must exist -3 = All of these lumps must exist -*/ - -gamedetect -{ - EXTENDED = 2; - - - BEHAVIOR = 2; - - E#M# = 2; - - MAP?? = 1; -} - - -/* -MAP LUMP NAMES -Map lumps are loaded with the map as long as they are right after each other. When the editor -meets a lump which is not defined in this list it will ignore the map if not satisfied. -The order of items defines the order in which lumps will be written to WAD file on save. -To indicate the map header lump, use ~MAP - -Legenda: -required = Lump is required to exist. -blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use) -nodebuild = The nodebuilder generates this lump. -allowempty = The nodebuilder is allowed to leave this lump empty. -script = This lump is a text-based script. Specify the filename of the script configuration to use. -*/ - -maplumpnames -{ - ~MAP - { - required = true; - blindcopy = true; - nodebuild = false; - } - - THINGS - { - required = true; - nodebuild = true; - allowempty = true; - } - - LINEDEFS - { - required = true; - nodebuild = true; - allowempty = false; - } - - SIDEDEFS - { - required = true; - nodebuild = true; - allowempty = false; - } - - VERTEXES - { - required = true; - nodebuild = true; - allowempty = false; - } - - SEGS - { - required = false; - nodebuild = true; - allowempty = false; - } - - SSECTORS - { - required = false; - nodebuild = true; - allowempty = false; - } - - NODES - { - required = false; - nodebuild = true; - allowempty = false; - } - - SECTORS - { - required = true; - nodebuild = true; - allowempty = false; - } - - REJECT - { - required = false; - nodebuild = true; - allowempty = false; - } - - BLOCKMAP - { - required = false; - nodebuild = true; - allowempty = true; - } -} - -scriptlumpnames -{ - MAINCFG - { - script = "SOC.cfg"; - } - - OBJCTCFG - { - script = "SOC.cfg"; - } - - SOC_ - { - script = "SOC.cfg"; - isprefix = true; - } - - LUA_ - { - script = "Lua.cfg"; - isprefix = true; - } -} - -// DEFAULT SECTOR BRIGHTNESS LEVELS -sectorbrightness -{ - 255; - 248; - 240; - 232; - 224; - 216; - 208; - 200; - 192; - 184; - 176; - 168; - 160; - 152; - 144; - 136; - 128; - 120; - 112; - 104; - 96; - 88; - 80; - 72; - 64; - 56; - 48; - 40; - 32; - 24; - 16; - 8; - 0; -} - -// SECTOR TYPES----------------------------------------------------------------- -sectortypes -{ - 0 = "Normal"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Tilt)"; - 7 = "Death Pit (No Camera Tilt)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (Anywhere in Sector)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy FOF"; - 16 = "Trigger Line Ex. (Pushable Objects)"; - 32 = "Trigger Line Ex. (Anywhere, All Players)"; - 48 = "Trigger Line Ex. (Floor Touch, All Players)"; - 64 = "Trigger Line Ex. (Anywhere in Sector)"; - 80 = "Trigger Line Ex. (Floor Touch)"; - 96 = "Trigger Line Ex. (Emerald Check)"; - 112 = "Trigger Line Ex. (NiGHTS Mare)"; - 128 = "Check for Linedef Executor on FOFs"; - 144 = "Egg Capsule"; - 160 = "Special Stage Time/Rings Parameters"; - 176 = "Custom Global Gravity"; - 512 = "Wind/Current"; - 1024 = "Conveyor Belt"; - 1280 = "Speed Pad"; - 4096 = "Star Post Activator"; - 8192 = "Exit/Special Stage Pit/Return Flag"; - 12288 = "CTF Red Team Base"; - 16384 = "CTF Blue Team Base"; - 20480 = "Fan Sector"; - 24576 = "Super Sonic Transform"; - 28672 = "Force Spin"; - 32768 = "Zoom Tube Start"; - 36864 = "Zoom Tube End"; - 40960 = "Circuit Finish Line"; - 45056 = "Rope Hang"; - 49152 = "Intangible to the Camera"; -} - - -// GENERALISED SECTOR TYPES----------------------------------------------------------------- -gen_sectortypes -{ - first - { - 0 = "Normal"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Tilt)"; - 7 = "Death Pit (No Camera Tilt)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (Anywhere in Sector)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy FOF"; - } - - second - { - 0 = "Normal"; - 16 = "Trigger Line Ex. (Pushable Objects)"; - 32 = "Trigger Line Ex. (Anywhere, All Players)"; - 48 = "Trigger Line Ex. (Floor Touch, All Players)"; - 64 = "Trigger Line Ex. (Anywhere in Sector)"; - 80 = "Trigger Line Ex. (Floor Touch)"; - 96 = "Trigger Line Ex. (Emerald Check)"; - 112 = "Trigger Line Ex. (NiGHTS Mare)"; - 128 = "Check for Linedef Executor on FOFs"; - 144 = "Egg Capsule"; - 160 = "Special Stage Time/Rings Parameters"; - 176 = "Custom Global Gravity"; - } - - third - { - 0 = "Normal"; - 512 = "Wind/Current"; - 1024 = "Conveyor Belt"; - 1280 = "Speed Pad"; - } - - fourth - { - 0 = "Normal"; - 4096 = "Star Post Activator"; - 8192 = "Exit/Special Stage Pit/Return Flag"; - 12288 = "CTF Red Team Base"; - 16384 = "CTF Blue Team Base"; - 20480 = "Fan Sector"; - 24576 = "Super Sonic Transform"; - 28672 = "Force Spin"; - 32768 = "Zoom Tube Start"; - 36864 = "Zoom Tube End"; - 40960 = "Circuit Finish Line"; - 45056 = "Rope Hang"; - 49152 = "Intangible to the Camera"; - } -} - -// LINEDEF FLAGS -linedefflags -{ - 1 = "[0] Impassable"; - 2 = "[1] Block Enemies"; - 4 = "[2] Double-Sided"; - 8 = "[3] Upper Unpegged"; - 16 = "[4] Lower Unpegged"; - 32 = "[5] Slope Skew (E1)"; - 64 = "[6] Not Climbable"; - 128 = "[7] No Midtexture Skew (E2)"; - 256 = "[8] Peg Midtexture (E3)"; - 512 = "[9] Solid Midtexture (E4)"; - 1024 = "[10] Repeat Midtexture (E5)"; - 2048 = "[11] Netgame Only"; - 4096 = "[12] No Netgame"; - 8192 = "[13] Effect 6"; - 16384 = "[14] Bouncy Wall"; - 32768 = "[15] Transfer Line"; -} - -// Linedef flags UDMF translation table -// This is needed for copy/paste and prefabs to work properly -// When the UDMF field name is prefixed with ! it is inverted -linedefflagstranslation -{ - 1 = "blocking"; - 2 = "blockmonsters"; - 4 = "twosided"; - 8 = "dontpegtop"; - 16 = "dontpegbottom"; - 32 = "secret"; - 64 = "blocksound"; - 128 = "dontdraw"; - 256 = "mapped"; -} - -// LINEDEF ACTIVATIONS -linedefactivations -{ -} - -// LINEDEF TYPES -linedeftypes -{ - misc - { - title = "Miscellaneous"; - - 0 - { - title = "None"; - prefix = "(0)"; - } - - 1 - { - title = "Per-Sector Gravity"; - prefix = "(1)"; - flags64text = "[6] Flip in reverse gravity"; - } - - 5 - { - title = "Camera Scanner"; - prefix = "(5)"; - } - - 7 - { - title = "Sector Flat Alignment"; - prefix = "(7)"; - flags2048text = "[11] Don't align floor"; - flags4096text = "[12] Don't align ceiling"; - flags8192text = "[13] Use texture offsets"; - } - - 10 - { - title = "Culling Plane"; - prefix = "(10)"; - flags64text = "[6] Cull only while in sector"; - } - - 13 - { - title = "Heat Wave Effect"; - prefix = "(13)"; - } - - 40 - { - title = "Visual Portal Between Tagged Linedefs"; - prefix = "(40)"; - } - - 41 - { - title = "Horizon Effect"; - prefix = "(41)"; - } - - 50 - { - title = "Instantly Lower Floor on Level Load"; - prefix = "(50)"; - } - - 51 - { - title = "Instantly Raise Ceiling on Level Load"; - prefix = "(51)"; - } - - 63 - { - title = "Fake Floor/Ceiling Planes"; - prefix = "(63)"; - } - - 540 - { - title = "Floor Friction"; - prefix = "(540)"; - } - } - - parameters - { - title = "Parameters"; - - 2 - { - title = "Custom Exit"; - prefix = "(2)"; - flags2text = "[1] Check emeralds"; - flags64text = "[6] Skip score tally"; - } - - 3 - { - title = "Zoom Tube Parameters"; - prefix = "(3)"; - flags512text = "[9] Ignore player direction"; - } - - 4 - { - title = "Speed Pad Parameters"; - prefix = "(4)"; - flags512text = "[9] No teleport to center"; - flags1024text = "[10] Force spinning frames"; - } - - 8 - { - title = "Special Sector Properties"; - prefix = "(8)"; - flags32text = "[5] Invert precipitation"; - flags64text = "[6] Touch only ceiling"; - flags128text = "[7] Allow opposite gravity"; - flags256text = "[8] Touch sector edge"; - flags512text = "[9] Touch floor or ceiling"; - } - - 9 - { - title = "Chain Parameters"; - prefix = "(9)"; - flags32text = "[5] Swing instead of spin"; - flags64text = "[6] Player-turnable chain"; - flags128text = "[7] Make chain from maces"; - flags256text = "[8] Spawn mace at origin"; - flags512text = "[9] Don't clip inside ground"; - flags1024text = "[10] No distance check"; - } - - 11 - { - title = "Rope Hang Parameters"; - prefix = "(11)"; - flags32text = "[5] Don't loop"; - flags64text = "[6] Static"; - } - - 12 - { - title = "Rock Spawner Parameters"; - prefix = "(12)"; - flags64text = "[6] Randomize speed"; - } - - 14 - { - title = "Bustable Block Parameters"; - prefix = "(14)"; - flags32text = "[5] Particles launch from center"; - } - - 15 - { - title = "Fan Particle Spawner Parameters"; - prefix = "(15)"; - } - - 16 - { - title = "Minecart Parameters"; - prefix = "(16)"; - } - - 64 - { - title = "Continuously Appearing/Disappearing FOF"; - prefix = "(64)"; - flags2text = "[1] Use control sector tag"; - flags64text = "[6] No sound effect"; - } - - 65 - { - title = "Bridge Thinker "; - prefix = "(65)"; - } - } - - polyobject - { - title = "PolyObject"; - - 20 - { - title = "First Line"; - prefix = "(20)"; - } - - 21 - { - title = "Explicitly Include Line "; - prefix = "(21)"; - } - - 22 - { - title = "Parameters"; - prefix = "(22)"; - flags64text = "[6] Trigger linedef executor"; - flags128text = "[7] Intangible"; - flags256text = "[8] Stopped by pushables"; - flags512text = "[9] Render flats"; - } - - 30 - { - title = "Waving Flag"; - prefix = "(30)"; - } - - 31 - { - title = "Displacement by Front Sector"; - prefix = "(31)"; - } - - 32 - { - title = "Angular Displacement by Front Sector"; - prefix = "(32)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't turn players"; - flags512text = "[9] Turn all objects"; - } - } - - planemove - { - title = "Plane Movement"; - - 52 - { - title = "Continuously Falling Sector"; - prefix = "(52)"; - flags64text = "[6] Continuously rising"; - } - - 53 - { - title = "Continuous Floor/Ceiling Mover"; - prefix = "(53)"; - } - - 54 - { - title = "Continuous Floor Mover"; - prefix = "(54)"; - } - - 55 - { - title = "Continuous Ceiling Mover"; - prefix = "(55)"; - } - - 56 - { - title = "Continuous Two-Speed Floor/Ceiling Mover"; - prefix = "(56)"; - } - - 57 - { - title = "Continuous Two-Speed Floor Mover"; - prefix = "(57)"; - } - - 58 - { - title = "Continuous Two-Speed Ceiling Mover"; - prefix = "(58)"; - } - - 59 - { - title = "Activate Moving Platform"; - prefix = "(59)"; - flags64text = "[6] Move upwards at start"; - } - - 60 - { - title = "Activate Moving Platform (Adjustable Speed)"; - prefix = "(60)"; - flags64text = "[6] Move upwards at start"; - } - - 61 - { - title = "Crusher (Ceiling to Floor)"; - prefix = "(61)"; - flags512text = "[9] Double, constant speed"; - } - - 62 - { - title = "Crusher (Floor to Ceiling)"; - prefix = "(62)"; - flags512text = "[9] Double, constant speed"; - } - - 66 - { - title = "Move Floor by Displacement"; - prefix = "(66)"; - flags64text = "[6] Inverse movement"; - } - - 67 - { - title = "Move Ceiling by Displacement"; - prefix = "(67)"; - flags64text = "[6] Inverse movement"; - } - - 68 - { - title = "Move Floor and Ceiling by Displacement"; - prefix = "(68)"; - flags64text = "[6] Inverse movement"; - } - } - - fofsolid - { - title = "FOF (solid)"; - - 100 - { - title = "Solid, Opaque"; - prefix = "(100)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 101 - { - title = "Solid, Opaque, No Shadow"; - prefix = "(101)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1DF"; - } - - 102 - { - title = "Solid, Translucent"; - prefix = "(102)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Render insides"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "195F"; - flags643dfloorflagsadd = "7C80"; - } - - 103 - { - title = "Solid, Sides Only"; - prefix = "(103)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1CF"; - } - - 104 - { - title = "Solid, No Sides"; - prefix = "(104)"; - flags32text = "[5] Only block player"; - flags64text = "[6] Cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1D7"; - flags643dfloorflagsremove = "40"; - } - - 105 - { - title = "Solid, Invisible"; - prefix = "(105)"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "47"; - } - - 140 - { - title = "Intangible from Bottom, Opaque"; - prefix = "(140)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "200841F"; - flags643dfloorflagsadd = "40"; - } - - 141 - { - title = "Intangible from Bottom, Translucent"; - prefix = "(141)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Render insides/block non-plr"; - 3dfloor = true; - 3dfloorflags = "200191F"; - flags1283dfloorflagsadd = "7C80"; - flags643dfloorflagsadd = "40"; - } - - 142 - { - title = "Intangible from Bottom, Translucent, No Sides"; - prefix = "(142)"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Render insides/block non-plr"; - 3dfloor = true; - 3dfloorflags = "2001917"; - flags1283dfloorflagsadd = "7C80"; - flags643dfloorflagsadd = "40"; - } - - 143 - { - title = "Intangible from Top, Opaque"; - prefix = "(143)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "400841F"; - flags643dfloorflagsadd = "40"; - } - - 144 - { - title = "Intangible from Top, Translucent"; - prefix = "(144)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Render insides/block non-plr"; - 3dfloor = true; - 3dfloorflags = "400191F"; - flags1283dfloorflagsadd = "7C80"; - flags643dfloorflagsadd = "40"; - } - - 145 - { - title = "Intangible from Top, Translucent, No Sides"; - prefix = "(145)"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Render insides/block non-plr"; - 3dfloor = true; - 3dfloorflags = "4001917"; - flags1283dfloorflagsadd = "7C80"; - flags643dfloorflagsadd = "40"; - } - - 146 - { - title = "Only Tangible from Sides"; - prefix = "(146)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "600800F"; - } - } - - fofintangible - { - title = "FOF (intangible)"; - - 120 - { - title = "Water, Opaque"; - prefix = "(120)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "8F39"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 121 - { - title = "Water, Translucent"; - prefix = "(121)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "9F39"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 122 - { - title = "Water, Opaque, No Sides"; - prefix = "(122)"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "F31"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 123 - { - title = "Water, Translucent, No Sides"; - prefix = "(123)"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "1F31"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 124 - { - title = "Goo Water, Translucent"; - prefix = "(124)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "209F39"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 125 - { - title = "Goo Water, Translucent, No Sides"; - prefix = "(125)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Use two light levels"; - flags512text = "[9] Use target light level"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "201F31"; - flags643dfloorflagsadd = "20000"; - flags5123dfloorflagsadd = "80000000"; - flags10243dfloorflagsadd = "40000000"; - } - - 220 - { - title = "Intangible, Opaque"; - prefix = "(220)"; - flags8text = "[3] Slope skew sides"; - 3dfloor = true; - 3dfloorflags = "8F19"; - } - - 221 - { - title = "Intangible, Translucent"; - prefix = "(221)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Cast shadow"; - 3dfloor = true; - 3dfloorflags = "1B59"; - flags643dfloorflagsremove = "40"; - } - - 222 - { - title = "Intangible, Sides Only"; - prefix = "(222)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Cast shadow"; - 3dfloor = true; - 3dfloorflags = "8249"; - flags643dfloorflagsremove = "240"; - } - - 223 - { - title = "Intangible, Invisible"; - prefix = "(223)"; - 3dfloor = true; - 3dfloorflags = "41"; - } - } - - fofmoving - { - title = "FOF (moving)"; - - 150 - { - title = "Air Bobbing"; - prefix = "(150)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 151 - { - title = "Air Bobbing (Adjustable)"; - prefix = "(151)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 152 - { - title = "Reverse Air Bobbing (Adjustable)"; - prefix = "(152)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 160 - { - title = "Floating, Bobbing"; - prefix = "(160)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "4019F"; - } - - 190 - { - title = "Rising Platform, Solid, Opaque"; - prefix = "(190)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 191 - { - title = "Rising Platform, Solid, Opaque, No Shadow"; - prefix = "(191)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1DF"; - } - - 192 - { - title = "Rising Platform, Solid, Translucent"; - prefix = "(192)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "195F"; - } - - 193 - { - title = "Rising Platform, Solid, Invisible"; - prefix = "(193)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "47"; - } - - 194 - { - title = "Rising Platform, Intangible from Bottom, Opaque"; - prefix = "(194)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash, no shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "200841F"; - flags643dfloorflagsadd = "40"; - } - - 195 - { - title = "Rising Platform, Intangible from Bottom, Translucent"; - prefix = "(195)"; - flags2text = "[1] Sink when stepped on"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash, no shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "2009D1F"; - flags643dfloorflagsadd = "40"; - } - } - - fofcrumbling - { - title = "FOF (crumbling)"; - - 170 - { - title = "Crumbling, Respawn"; - prefix = "(170)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "10019F"; - } - - 171 - { - title = "Crumbling, No Respawn"; - prefix = "(171)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "80019F"; - } - - 172 - { - title = "Crumbling, Respawn, Intangible from Bottom"; - prefix = "(172)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "210841F"; - flags643dfloorflagsadd = "40"; - } - - 173 - { - title = "Crumbling, No Respawn, Intangible from Bottom"; - prefix = "(173)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "218841F"; - flags643dfloorflagsadd = "40"; - } - - 174 - { - title = "Crumbling, Respawn, Int. from Bottom, Translucent"; - prefix = "(174)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "210959F"; - flags643dfloorflagsadd = "40"; - } - - 175 - { - title = "Crumbling, No Respawn, Int. from Bottom, Translucent"; - prefix = "(175)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Don't cast shadow"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "218959F"; - flags643dfloorflagsadd = "40"; - } - - 176 - { - title = "Crumbling, Respawn, Floating, Bobbing"; - prefix = "(176)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "14019F"; - } - - 177 - { - title = "Crumbling, No Respawn, Floating, Bobbing"; - prefix = "(177)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1C019F"; - } - - 178 - { - title = "Crumbling, Respawn, Floating"; - prefix = "(178)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "14019F"; - } - - 179 - { - title = "Crumbling, No Respawn, Floating"; - prefix = "(179)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "1C019F"; - } - - 180 - { - title = "Crumbling, Respawn, Air Bobbing"; - prefix = "(180)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags64text = "[6] Spindash to move"; - flags128text = "[7] Only block non-players"; - 3dfloor = true; - 3dfloorflags = "10019F"; - } - } - - fofspecial - { - title = "FOF (special)"; - - 200 - { - title = "Light Block"; - prefix = "(200)"; - 3dfloor = true; - 3dfloorflags = "20201"; - } - - 201 - { - title = "Half Light Block"; - prefix = "(201)"; - 3dfloor = true; - 3dfloorflags = "201"; - } - - 202 - { - title = "Fog Block"; - prefix = "(202)"; - 3dfloor = true; - 3dfloorflags = "3EF19"; - } - - 250 - { - title = "Mario Block"; - prefix = "(250)"; - flags32text = "[5] Invisible block"; - flags64text = "[6] Brick block"; - 3dfloor = true; - 3dfloorflags = "40019F"; - } - - 251 - { - title = "Thwomp Block"; - prefix = "(251)"; - flags512text = "[9] Custom crushing sound"; - flags1024text = "[10] Custom speed"; - 3dfloor = true; - 3dfloorflags = "19F"; - } - - 252 - { - title = "Shatter Block"; - prefix = "(252)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Shatter only from below"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorflags = "8800019"; - flags643dfloorflagsadd = "200006"; - } - - 253 - { - title = "Shatter Block, Translucent"; - prefix = "(253)"; - flags8text = "[3] Slope skew sides"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorflags = "8801019"; - } - - 254 - { - title = "Bustable Block"; - prefix = "(254)"; - flags8text = "[3] Slope skew sides"; - flags64text = "[6] Strong characters only"; - flags128text = "[7] Only block non-players"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorflags = "80001F"; - flags643dfloorflagsadd = "20000000"; - } - - 255 - { - title = "Spin-Bustable Block"; - prefix = "(255)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorflags = "1080001F"; - } - - 256 - { - title = "Spin-Bustable Block, Translucent"; - prefix = "(256)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorflags = "1080101F"; - } - - 257 - { - title = "Quicksand"; - prefix = "(257)"; - flags8text = "[3] Slope skew sides"; - flags1024text = "[10] Ripple effect"; - 3dfloor = true; - 3dfloorflags = "1008219"; - flags10243dfloorflagsadd = "40000000"; - } - - 258 - { - title = "Laser"; - prefix = "(258)"; - flags8text = "[3] Slope skew sides"; - flags32text = "[5] Don't damage bosses"; - 3dfloor = true; - 3dfloorflags = "959"; - } - - 259 - { - title = "Custom FOF"; - prefix = "(259)"; - flags32text = "[5] Only block player"; - flags128text = "[7] Only block non-players"; - flags512text = "[9] Shattered by pushables"; - flags1024text = "[10] Trigger linedef executor"; - 3dfloor = true; - 3dfloorcustom = true; - } - } - - linedeftrigger - { - title = "Linedef Executor Trigger"; - - 300 - { - title = "Continuous"; - prefix = "(300)"; - } - - 301 - { - title = "Each Time"; - prefix = "(301)"; - flags16384text = "[14] Also trigger on exit"; - } - - 302 - { - title = "Once"; - prefix = "(302)"; - } - - 303 - { - title = "Ring Count - Continuous"; - prefix = "(303)"; - flags2text = "[1] Rings greater or equal"; - flags64text = "[6] Rings less or equal"; - flags512text = "[9] Consider all players"; - } - - 304 - { - title = "Ring Count - Once"; - prefix = "(304)"; - flags2text = "[1] Rings greater or equal"; - flags64text = "[6] Rings less or equal"; - flags512text = "[9] Consider all players"; - } - - 305 - { - title = "Character Ability - Continuous"; - prefix = "(305)"; - } - - 306 - { - title = "Character Ability - Each Time"; - prefix = "(306)"; - flags16384text = "[14] Also trigger on exit"; - } - - 307 - { - title = "Character Ability - Once"; - prefix = "(307)"; - } - - 308 - { - title = "Race Only - Once"; - prefix = "(308)"; - } - - 309 - { - title = "CTF Red Team - Continuous"; - prefix = "(309)"; - } - - 310 - { - title = "CTF Red Team - Each Time"; - prefix = "(310)"; - flags16384text = "[14] Also trigger on exit"; - } - - 311 - { - title = "CTF Blue Team - Continuous"; - prefix = "(311)"; - } - - 312 - { - title = "CTF Blue Team - Each Time"; - prefix = "(312)"; - flags16384text = "[14] Also trigger on exit"; - } - - 313 - { - title = "No More Enemies - Once"; - prefix = "(313)"; - } - - 314 - { - title = "Number of Pushables - Continuous"; - prefix = "(314)"; - flags64text = "[6] Number greater or equal"; - flags512text = "[9] Number less"; - } - - 315 - { - title = "Number of Pushables - Once"; - prefix = "(315)"; - flags64text = "[6] Number greater or equal"; - flags512text = "[9] Number less"; - } - - 317 - { - title = "Condition Set Trigger - Continuous"; - prefix = "(317)"; - } - - 318 - { - title = "Condition Set Trigger - Once"; - prefix = "(318)"; - } - - 319 - { - title = "Unlockable - Continuous"; - prefix = "(319)"; - } - - 320 - { - title = "Unlockable - Once"; - prefix = "(320)"; - } - - 321 - { - title = "Trigger After X Calls - Continuous"; - prefix = "(321)"; - flags64text = "[6] Trigger more than once"; - - } - - 322 - { - title = "Trigger After X Calls - Each Time"; - prefix = "(322)"; - flags64text = "[6] Trigger more than once"; - } - - 323 - { - title = "NiGHTSerize - Each Time"; - prefix = "(323)"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run only if player is NiGHTS"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags16384text = "[14] Run if no more mares"; - flags32768text = "[15] Run if player is not NiGHTS"; - } - - 324 - { - title = "NiGHTSerize - Once"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run only if player is NiGHTS"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags16384text = "[14] Run if no more mares"; - flags32768text = "[15] Run if player is not NiGHTS"; - prefix = "(324)"; - } - - 325 - { - title = "De-NiGHTSerize - Each Time"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run if anyone is NiGHTS"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags32768text = "[15] Run if no one is NiGHTS"; - prefix = "(325)"; - } - - 326 - { - title = "De-NiGHTSerize - Once"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run if anyone is NiGHTS"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags32768text = "[15] Run if no one is NiGHTS"; - prefix = "(326)"; - } - - 327 - { - title = "NiGHTS Lap - Each Time"; - flags2text = "[1] Mare >= Front X Offset"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - prefix = "(327)"; - } - - 328 - { - title = "NiGHTS Lap - Once"; - flags2text = "[1] Mare >= Front X Offset"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - prefix = "(328)"; - } - - 329 - { - title = "Ideya Capture Touch - Each Time"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run regardless of spheres"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags16384text = "[14] Only if not enough spheres"; - flags32768text = "[15] Run when entering Capture"; - prefix = "(329)"; - } - - 330 - { - title = "Ideya Capture Touch - Once"; - flags2text = "[1] Mare >= Front X Offset"; - flags8text = "[3] Run regardless of spheres"; - flags16text = "[4] Count from lowest of players"; - flags32text = "[5] Lap <= Front Y Offset"; - flags64text = "[6] Mare <= Front X Offset"; - flags128text = "[7] Lap >= Front Y Offset"; - flags256text = "[8] Count laps from Bonus Time"; - flags512text = "[9] Count from triggering player"; - flags16384text = "[14] Only if not enough spheres"; - flags32768text = "[15] Run when entering Capture"; - prefix = "(330)"; - } - - 331 - { - title = "Player Skin - Continuous"; - flags64text = "[6] Disable for this skin"; - prefix = "(331)"; - } - - 332 - { - title = "Player Skin - Each Time"; - flags64text = "[6] Disable for this skin"; - prefix = "(332)"; - } - - 333 - { - title = "Player Skin - Once"; - flags64text = "[6] Disable for this skin"; - prefix = "(333)"; - } - - 399 - { - title = "Level Load"; - prefix = "(399)"; - } - } - - linedefexecsector - { - title = "Linedef Executor (sector)"; - - 400 - { - title = "Set Tagged Sector's Floor Height/Texture"; - prefix = "(400)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Keep floor flat"; - } - - 401 - { - title = "Set Tagged Sector's Ceiling Height/Texture"; - prefix = "(401)"; - flags8text = "[3] Set delay by backside sector"; - } - - 402 - { - title = "Set Tagged Sector's Light Level"; - prefix = "(402)"; - flags8text = "[3] Set delay by backside sector"; - } - - 409 - { - title = "Change Tagged Sector's Tag"; - prefix = "(409)"; - flags8text = "[3] Set delay by backside sector"; - } - - 410 - { - title = "Change Front Sector's Tag"; - prefix = "(410)"; - flags8text = "[3] Set delay by backside sector"; - } - - 416 - { - title = "Start Adjustable Flickering Light"; - prefix = "(416)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Second level from back"; - } - - 417 - { - title = "Start Adjustable Pulsating Light"; - prefix = "(417)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Second level from back"; - } - - 418 - { - title = "Start Adjustable Blinking Light (unsynchronized)"; - prefix = "(418)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Second level from back"; - } - - 419 - { - title = "Start Adjustable Blinking Light (synchronized)"; - prefix = "(419)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Second level from back"; - } - - 420 - { - title = "Fade Light Level"; - prefix = "(420)"; - flags8text = "[3] Set delay by backside sector"; - flags16text = "[4] Set params by X/Y offsets"; - flags512text = "[9] Speed = Tic Duration"; - flags1024text = "[10] Override existing fade"; - } - - 421 - { - title = "Stop Lighting Effect"; - prefix = "(421)"; - flags8text = "[3] Set delay by backside sector"; - } - - 435 - { - title = "Change Plane Scroller Direction"; - prefix = "(435)"; - flags8text = "[3] Set delay by backside sector"; - } - } - - linedefexecplane - { - title = "Linedef Executor (plane movement)"; - - 403 - { - title = "Move Tagged Sector's Floor"; - prefix = "(403)"; - flags2text = "[1] Trigger linedef executor"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Change floor flat"; - } - - 404 - { - title = "Move Tagged Sector's Ceiling"; - prefix = "(404)"; - flags2text = "[1] Trigger linedef executor"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Change ceiling flat"; - } - - 405 - { - title = "Move Floor According to Front Texture Offsets"; - prefix = "(405)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Move instantly"; - } - - 407 - { - title = "Move Ceiling According to Front Texture Offsets"; - prefix = "(407)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Move instantly"; - } - - 411 - { - title = "Stop Plane Movement"; - prefix = "(411)"; - flags8text = "[3] Set delay by backside sector"; - } - - 428 - { - title = "Start Platform Movement"; - prefix = "(428)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Move upwards at start"; - } - - 429 - { - title = "Crush Ceiling Once"; - prefix = "(429)"; - flags8text = "[3] Set delay by backside sector"; - flags512text = "[9] Double, constant speed"; - } - - 430 - { - title = "Crush Floor Once"; - prefix = "(430)"; - flags8text = "[3] Set delay by backside sector"; - } - - 431 - { - title = "Crush Floor and Ceiling Once"; - prefix = "(431)"; - flags8text = "[3] Set delay by backside sector"; - flags512text = "[9] Double, constant speed"; - } - } - - linedefexecplayer - { - title = "Linedef Executor (player/object)"; - - 412 - { - title = "Teleporter"; - prefix = "(412)"; - flags2text = "[1] Silent"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Retain angle"; - flags256text = "[8] Relative, silent"; - flags512text = "[9] Retain momentum"; - } - - 425 - { - title = "Change Object State"; - prefix = "(425)"; - flags8text = "[3] Set delay by backside sector"; - } - - 426 - { - title = "Stop Object"; - prefix = "(426)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Teleport to sector center"; - } - - 427 - { - title = "Award Score"; - prefix = "(427)"; - flags8text = "[3] Set delay by backside sector"; - } - - 432 - { - title = "Enable/Disable 2D Mode"; - prefix = "(432)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Return to 3D"; - } - - 433 - { - title = "Enable/Disable Gravity Flip"; - prefix = "(433)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Return to normal"; - } - - 434 - { - title = "Award Power-Up"; - prefix = "(434)"; - flags2text = "[1] Use back upper texture"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] No time limit"; - } - - 437 - { - title = "Disable Player Control"; - prefix = "(437)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Allow jumping"; - } - - 438 - { - title = "Change Object Size"; - prefix = "(438)"; - flags8text = "[3] Set delay by backside sector"; - } - - 442 - { - title = "Change Object Type State"; - prefix = "(442)"; - flags8text = "[3] Set delay by backside sector"; - } - - 457 - { - title = "Track Object's Angle"; - prefix = "(457)"; - flags8text = "[3] Set delay by backside sector"; - flags128text = "[7] Don't stop after first fail"; - } - - 458 - { - title = "Stop Tracking Object's Angle"; - prefix = "(458)"; - flags8text = "[3] Set delay by backside sector"; - } - - 460 - { - title = "Award Rings"; - prefix = "(460)"; - } - - 461 - { - title = "Spawn Object"; - prefix = "(461)"; - flags64text = "[6] Spawn inside a range"; - } - - 462 - { - title = "Stop Timer/Exit Stage in Record Attack"; - prefix = "(462)"; - } - } - - linedefexecmisc - { - title = "Linedef Executor (misc.)"; - - 413 - { - title = "Change Music"; - prefix = "(413)"; - flags2text = "[1] Keep after death"; - flags8text = "[3] Set delay by backside sector"; - flags32text = "[5] Seek to current song position"; - flags64text = "[6] For everyone"; - flags128text = "[7] Fade to custom volume"; - flags512text = "[9] Don't loop"; - flags16384text = "[14] Force music reload"; - } - - 414 - { - title = "Play Sound Effect"; - prefix = "(414)"; - flags2text = "[1] From calling sector"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] From nowhere for triggerer"; - flags512text = "[9] For everyone"; - flags1024text = "[10] From tagged sectors"; - } - - 415 - { - title = "Run Script"; - prefix = "(415)"; - flags8text = "[3] Set delay by backside sector"; - } - - 422 - { - title = "Switch to Cut-Away View"; - prefix = "(422)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Adjust pitch"; - } - - 423 - { - title = "Change Sky"; - prefix = "(423)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] For everyone"; - } - - 424 - { - title = "Change Weather"; - prefix = "(424)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] For everyone"; - } - - 436 - { - title = "Shatter FOF"; - prefix = "(436)"; - flags8text = "[3] Set delay by backside sector"; - } - - 439 - { - title = "Change Tagged Linedef's Textures"; - prefix = "(439)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Only existing"; - } - - 440 - { - title = "Start Metal Sonic Race"; - prefix = "(440)"; - flags8text = "[3] Set delay by backside sector"; - } - - 441 - { - title = "Condition Set Trigger"; - prefix = "(441)"; - flags8text = "[3] Set delay by backside sector"; - } - - 443 - { - title = "Call Lua Function"; - prefix = "(443)"; - flags8text = "[3] Set delay by backside sector"; - } - - 444 - { - title = "Earthquake"; - prefix = "(444)"; - flags8text = "[3] Set delay by backside sector"; - } - - - 445 - { - title = "Make FOF Disappear/Reappear"; - prefix = "(445)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Reappear"; - } - - 446 - { - title = "Make FOF Crumble"; - prefix = "(446)"; - flags2text = "[1] Flags determine respawn"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't respawn"; - } - - 447 - { - title = "Change Tagged Sector's Colormap"; - prefix = "(447)"; - flags8text = "[3] Set delay by backside sector"; - flags16text = "[4] Front X/Y = Alpha"; - flags32text = "[5] Subtract Red value"; - flags64text = "[6] Subtract Green value"; - flags128text = "[7] Subtract Blue value"; - flags256text = "[8] Calc relative values"; - flags32768text = "[15] Use back side colormap"; - } - - 448 - { - title = "Change Skybox"; - prefix = "(448)"; - flags2text = "[1] Change centerpoint"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] For everyone"; - flags512text = "[9] Don't change viewpoint"; - } - - 450 - { - title = "Execute Linedef Executor (specific tag)"; - prefix = "(450)"; - flags8text = "[3] Set delay by backside sector"; - } - - 451 - { - title = "Execute Linedef Executor (random tag in range)"; - prefix = "(451)"; - flags8text = "[3] Set delay by backside sector"; - } - - 452 - { - title = "Set FOF Translucency"; - prefix = "(452)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Do not handle FF_TRANS"; - flags256text = "[8] Set relative to current val"; - } - - 453 - { - title = "Fade FOF"; - prefix = "(453)"; - flags2text = "[1] Do not handle FF_EXISTS"; - flags8text = "[3] Set delay by backside sector"; - flags32text = "[5] No collision during fade"; - flags64text = "[6] Do not handle FF_TRANS"; - flags128text = "[7] Do not handle lighting"; - flags256text = "[8] Set relative to current val"; - flags512text = "[9] Speed = Tic Duration"; - flags1024text = "[10] Override existing fade"; - flags16384text = "[14] Do not handle collision"; - flags32768text = "[15] Use exact alpha in OGL"; - } - - 454 - { - title = "Stop Fading FOF"; - prefix = "(454)"; - flags2text = "[1] Do not finalize collision"; - flags8text = "[3] Set delay by backside sector"; - } - - 455 - { - title = "Fade Tagged Sector's Colormap"; - prefix = "(455)"; - flags8text = "[3] Set delay by backside sector"; - flags16text = "[4] Front X/Y = Alpha"; - flags32text = "[5] Subtract Red value"; - flags64text = "[6] Subtract Green value"; - flags128text = "[7] Subtract Blue value"; - flags256text = "[8] Calc relative values"; - flags512text = "[9] Speed = Tic Duration"; - flags1024text = "[10] Override existing fade"; - flags16384text = "[14] Fade from invisible black"; - flags32768text = "[15] Use back side colormap"; - } - - 456 - { - title = "Stop Fading Tagged Sector's Colormap"; - prefix = "(456)"; - flags8text = "[3] Set delay by backside sector"; - } - - 459 - { - title = "Control Text Prompt"; - prefix = "(459)"; - flags2text = "[1] Close text prompt"; - flags8text = "[3] Set delay by backside sector"; - flags32text = "[5] Run executor tag on close"; - flags64text = "[6] For everyone"; - flags128text = "[7] Do not block controls"; - flags256text = "[8] Do not freeze time"; - flags32768text = "[15] Find prompt by name"; - } - } - - linedefexecpoly - { - title = "Linedef Executor (polyobject)"; - - 480 - { - title = "Door Slide"; - prefix = "(480)"; - flags8text = "[3] Set delay by backside sector"; - } - - 481 - { - title = "Door Swing"; - prefix = "(481)"; - flags8text = "[3] Set delay by backside sector"; - } - - 482 - { - title = "Move"; - prefix = "(482)"; - flags8text = "[3] Set delay by backside sector"; - } - - 483 - { - title = "Move, Override"; - prefix = "(483)"; - flags8text = "[3] Set delay by backside sector"; - } - - 484 - { - title = "Rotate Right"; - prefix = "(484)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't turn players"; - flags512text = "[9] Turn all objects"; - } - - 485 - { - title = "Rotate Right, Override"; - prefix = "(485)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't turn players"; - flags512text = "[9] Turn all objects"; - } - - 486 - { - title = "Rotate Left"; - prefix = "(486)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't turn players"; - flags512text = "[9] Turn all objects"; - } - - 487 - { - title = "Rotate Left, Override"; - prefix = "(487)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Don't turn players"; - flags512text = "[9] Turn all objects"; - } - - 488 - { - title = "Move by Waypoints"; - prefix = "(488)"; - flags8text = "[3] Set delay by backside sector"; - flags32text = "[5] Reverse order"; - flags128text = "[7] There and back"; - flags256text = "[8] Return when done"; - flags512text = "[9] Loop movement"; - } - - 489 - { - title = "Turn Invisible, Intangible"; - prefix = "(489)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Only invisible"; - } - - 490 - { - title = "Turn Visible, Tangible"; - prefix = "(490)"; - flags8text = "[3] Set delay by backside sector"; - flags64text = "[6] Only visible"; - } - - 491 - { - title = "Set Translucency"; - prefix = "(491)"; - flags8text = "[3] Set delay by backside sector"; - flags16text = "[4] Set raw alpha by Front X"; - flags256text = "[8] Calc relative values"; - } - - 492 - { - title = "Fade Translucency"; - prefix = "(492)"; - flags8text = "[3] Set delay by backside sector"; - flags16text = "[4] Set raw alpha by Front X"; - flags32text = "[5] No collision during fade"; - flags256text = "[8] Calc relative values"; - flags512text = "[9] Speed = Tic Duration"; - flags1024text = "[10] Override existing fade"; - flags16384text = "[14] Do not handle collision"; - } - } - - wallscroll - { - title = "Wall Scrolling"; - - 500 - { - title = "Scroll Wall Front Side Left"; - prefix = "(500)"; - } - - 501 - { - title = "Scroll Wall Front Side Right"; - prefix = "(501)"; - } - - 502 - { - title = "Scroll Wall According to Linedef"; - prefix = "(502)"; - } - - 503 - { - title = "Scroll Wall According to Linedef (Accelerative)"; - prefix = "(503)"; - } - - 504 - { - title = "Scroll Wall According to Linedef (Displacement)"; - prefix = "(504)"; - } - - 505 - { - title = "Scroll Texture by Front Side Offsets"; - prefix = "(505)"; - } - - 506 - { - title = "Scroll Texture by Back Side Offsets"; - prefix = "(506)"; - } - } - - planescroll - { - title = "Plane Scrolling"; - - 510 - { - title = "Scroll Floor Texture"; - prefix = "(510)"; - } - - 511 - { - title = "Scroll Floor Texture (Accelerative)"; - prefix = "(511)"; - } - - 512 - { - title = "Scroll Floor Texture (Displacement)"; - prefix = "(512)"; - } - - 513 - { - title = "Scroll Ceiling Texture"; - prefix = "(513)"; - } - - 514 - { - title = "Scroll Ceiling Texture (Accelerative)"; - prefix = "(514)"; - } - - 515 - { - title = "Scroll Ceiling Texture (Displacement)"; - prefix = "(515)"; - } - - 520 - { - title = "Carry Objects on Floor"; - prefix = "(520)"; - } - - 521 - { - title = "Carry Objects on Floor (Accelerative)"; - prefix = "(521)"; - flags64text = "[6] Even across edges"; - } - - 522 - { - title = "Carry Objects on Floor (Displacement)"; - prefix = "(522)"; - } - - 523 - { - title = "Carry Objects on Ceiling"; - prefix = "(523)"; - flags64text = "[6] Even across edges"; - } - - 524 - { - title = "Carry Objects on Ceiling (Accelerative)"; - prefix = "(524)"; - } - - 525 - { - title = "Carry Objects on Ceiling (Displacement)"; - prefix = "(525)"; - } - - 530 - { - title = "Scroll Floor Texture and Carry Objects"; - prefix = "(530)"; - flags64text = "[6] Even across edges"; - } - - 531 - { - title = "Scroll Floor Texture and Carry Objects (Accelerative)"; - prefix = "(531)"; - } - - 532 - { - title = "Scroll Floor Texture and Carry Objects (Displacement)"; - prefix = "(532)"; - } - - 533 - { - title = "Scroll Ceiling Texture and Carry Objects"; - prefix = "(533)"; - flags64text = "[6] Even across edges"; - } - - 534 - { - title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; - prefix = "(534)"; - } - - 535 - { - title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; - prefix = "(535)"; - } - } - - pusher - { - title = "Pusher"; - - 541 - { - title = "Wind"; - prefix = "(541)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 542 - { - title = "Upwards Wind"; - prefix = "(542)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 543 - { - title = "Downwards Wind"; - prefix = "(543)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 544 - { - title = "Current"; - prefix = "(544)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 545 - { - title = "Upwards Current"; - prefix = "(545)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 546 - { - title = "Downwards Current"; - prefix = "(546)"; - flags512text = "[9] Player slides"; - flags64text = "[6] Even across edges"; - } - - 547 - { - title = "Push/Pull"; - prefix = "(547)"; - } - } - - light - { - title = "Lighting"; - - 600 - { - title = "Floor Lighting"; - prefix = "(600)"; - } - - 601 - { - title = "Ceiling Lighting"; - prefix = "(601)"; - } - - 602 - { - title = "Adjustable Pulsating Light"; - prefix = "(602)"; - } - - 603 - { - title = "Adjustable Flickering Light"; - prefix = "(603)"; - } - - 604 - { - title = "Adjustable Blinking Light (unsynchronized)"; - prefix = "(604)"; - } - - 605 - { - title = "Adjustable Blinking Light (synchronized)"; - prefix = "(605)"; - } - - 606 - { - title = "Colormap"; - prefix = "(606)"; - } - } - - slope - { - title = "Slope"; - - 700 - { - title = "Slope Frontside Floor"; - prefix = "(700)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 1; - } - - 701 - { - title = "Slope Frontside Ceiling"; - prefix = "(701)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 2; - } - - 702 - { - title = "Slope Frontside Floor and Ceiling"; - prefix = "(702)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 3; - } - - 703 - { - title = "Slope Frontside Floor and Backside Ceiling"; - prefix = "(703)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 9; - } - - 704 - { - title = "Slope Frontside Floor by 3 Tagged Vertex Things"; - prefix = "(704)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - flags8192text = "[13] Use tag and offsets"; - slope = "vertex"; - slopeargs = 0; - } - - 705 - { - title = "Slope Frontside Ceiling by 3 Tagged Vertex Things"; - prefix = "(705)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - flags8192text = "[13] Use tag and offsets"; - slope = "vertex"; - slopeargs = 1; - } - - 710 - { - title = "Slope Backside Floor"; - prefix = "(710)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 4; - } - - 711 - { - title = "Slope Backside Ceiling"; - prefix = "(711)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 8; - } - - 712 - { - title = "Slope Backside Floor and Ceiling"; - prefix = "(712)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 12; - } - - 713 - { - title = "Slope Backside Floor and Frontside Ceiling"; - prefix = "(713)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - slope = "regular"; - slopeargs = 6; - } - - 714 - { - title = "Slope Backside Floor by 3 Tagged Vertex Things"; - prefix = "(714)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - flags8192text = "[13] Use tag and offsets"; - slope = "vertex"; - slopeargs = 2; - } - - 715 - { - title = "Slope Backside Ceiling by 3 Tagged Vertex Things"; - prefix = "(715)"; - flags2048text = "[11] No physics"; - flags4096text = "[12] Dynamic"; - flags8192text = "[13] Use tag and offsets"; - slope = "vertex"; - slopeargs = 3; - } - - 720 - { - title = "Copy Frontside Floor Slope from Line Tag"; - prefix = "(720)"; - slope = "copy"; - slopeargs = 1; - } - - 721 - { - title = "Copy Frontside Ceiling Slope from Line Tag"; - prefix = "(721)"; - slope = "copy"; - slopeargs = 2; - } - - 722 - { - title = "Copy Frontside Floor and Ceiling Slope from Line Tag"; - prefix = "(722)"; - slope = "copy"; - slopeargs = 3; - } - - 799 - { - title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; - prefix = "(799)"; - } - } - - transwall - { - title = "Translucent Wall"; - - 900 - { - title = "90% Opaque"; - prefix = "(900)"; - } - - 901 - { - title = "80% Opaque"; - prefix = "(901)"; - } - - 902 - { - title = "70% Opaque"; - prefix = "(902)"; - } - - 903 - { - title = "60% Opaque"; - prefix = "(903)"; - } - - 904 - { - title = "50% Opaque"; - prefix = "(904)"; - } - - 905 - { - title = "40% Opaque"; - prefix = "(905)"; - } - - 906 - { - title = "30% Opaque"; - prefix = "(906)"; - } - - 907 - { - title = "20% Opaque"; - prefix = "(907)"; - } - - 908 - { - title = "10% Opaque"; - prefix = "(908)"; - } - - 909 - { - title = "Fog Wall"; - prefix = "(909)"; - } - } -} - - -// THING FLAGS -thingflags -{ - 1 = "[1] Extra"; - 2 = "[2] Flip"; - 4 = "[4] Special"; - 8 = "[8] Ambush"; -} - -// Thing flags UDMF translation table -// This is needed for copy/paste and prefabs to work properly -// When the UDMF field name is prefixed with ! it is inverted -thingflagstranslation -{ - 1 = "skill1"; - 2 = "skill2"; - 4 = "skill3"; - 8 = "ambush"; -} - -// THING FLAGS ERROR MASK -// Mask for the thing flags which indicates the options -// that make the same thing appear in the same modes -thingflagsmask1 = 7; // 1 + 2 + 4 -thingflagsmask2 = 0; - - -// THING TYPES------------------------------------------------------------------ -// Color values: 1-Dark_Blue 2-Dark_Green 3-Turqoise 4-Dark_Red 5-Purple 6-Brown 7-Gray -// 8-Dark_Gray 9-Blue 10-Green 11-Cyan 12-Red 13-Magenta -// 14-Yellow 15-White 16-Pink 17-Orange 18-Gold 19-Cream -thingtypes -{ - editor - { - color = 15; // White - arrow = 1; - title = ""; - error = -1; - width = 8; - height = 16; - sort = 1; - - 3328 = "3D Mode Start"; - } - - starts - { - color = 1; // Blue - arrow = 1; - title = "Player Starts"; - width = 16; - height = 48; - flags8text = "[8] Spawn on ceiling"; - sprite = "PLAYA0"; - - 1 - { - title = "Player 01 Start"; - sprite = "PLAYA0"; - } - 2 - { - title = "Player 02 Start"; - sprite = "PLAYA0"; - } - 3 - { - title = "Player 03 Start"; - sprite = "PLAYA0"; - } - 4 - { - title = "Player 04 Start"; - sprite = "PLAYA0"; - } - 5 - { - title = "Player 05 Start"; - sprite = "PLAYA0"; - } - 6 - { - title = "Player 06 Start"; - sprite = "PLAYA0"; - } - 7 - { - title = "Player 07 Start"; - sprite = "PLAYA0"; - } - 8 - { - title = "Player 08 Start"; - sprite = "PLAYA0"; - } - 9 - { - title = "Player 09 Start"; - sprite = "PLAYA0"; - } - 10 - { - title = "Player 10 Start"; - sprite = "PLAYA0"; - } - 11 - { - title = "Player 11 Start"; - sprite = "PLAYA0"; - } - 12 - { - title = "Player 12 Start"; - sprite = "PLAYA0"; - } - 13 - { - title = "Player 13 Start"; - sprite = "PLAYA0"; - } - 14 - { - title = "Player 14 Start"; - sprite = "PLAYA0"; - } - 15 - { - title = "Player 15 Start"; - sprite = "PLAYA0"; - } - 16 - { - title = "Player 16 Start"; - sprite = "PLAYA0"; - } - 17 - { - title = "Player 17 Start"; - sprite = "PLAYA0"; - } - 18 - { - title = "Player 18 Start"; - sprite = "PLAYA0"; - } - 19 - { - title = "Player 19 Start"; - sprite = "PLAYA0"; - } - 20 - { - title = "Player 20 Start"; - sprite = "PLAYA0"; - } - 21 - { - title = "Player 21 Start"; - sprite = "PLAYA0"; - } - 22 - { - title = "Player 22 Start"; - sprite = "PLAYA0"; - } - 23 - { - title = "Player 23 Start"; - sprite = "PLAYA0"; - } - 24 - { - title = "Player 24 Start"; - sprite = "PLAYA0"; - } - 25 - { - title = "Player 25 Start"; - sprite = "PLAYA0"; - } - 26 - { - title = "Player 26 Start"; - sprite = "PLAYA0"; - } - 27 - { - title = "Player 27 Start"; - sprite = "PLAYA0"; - } - 28 - { - title = "Player 28 Start"; - sprite = "PLAYA0"; - } - 29 - { - title = "Player 29 Start"; - sprite = "PLAYA0"; - } - 30 - { - title = "Player 30 Start"; - sprite = "PLAYA0"; - } - 31 - { - title = "Player 31 Start"; - sprite = "PLAYA0"; - } - 32 - { - title = "Player 32 Start"; - sprite = "PLAYA0"; - } - 33 - { - title = "Match Start"; - sprite = "NDRNA2A8"; - } - 34 - { - title = "CTF Red Team Start"; - sprite = "SIGNG0"; - } - 35 - { - title = "CTF Blue Team Start"; - sprite = "SIGNE0"; - } - } - - enemies - { - color = 9; // Light_Blue - arrow = 1; - title = "Enemies"; - - 100 - { - title = "Crawla (Blue)"; - sprite = "POSSA1"; - width = 24; - height = 32; - } - 101 - { - title = "Crawla (Red)"; - sprite = "SPOSA1"; - width = 24; - height = 32; - } - 102 - { - title = "Stupid Dumb Unnamed RoboFish"; - sprite = "FISHA0"; - width = 8; - height = 28; - angletext = "Jump strength"; - } - 103 - { - title = "Buzz (Gold)"; - sprite = "BUZZA1"; - width = 28; - height = 40; - flags8text = "[8] Cannot move"; - } - 104 - { - title = "Buzz (Red)"; - sprite = "RBUZA1"; - width = 28; - height = 40; - flags8text = "[8] Cannot move"; - } - 108 - { - title = "Deton"; - sprite = "DETNA1"; - width = 20; - height = 32; - } - 110 - { - title = "Turret"; - sprite = "TRETA1"; - width = 16; - height = 32; - } - 111 - { - title = "Pop-up Turret"; - sprite = "TURRI1"; - width = 12; - height = 64; - angletext = "Firing delay"; - } - 122 - { - title = "Spring Shell (Green)"; - sprite = "SSHLA1"; - width = 24; - height = 40; - } - 125 - { - title = "Spring Shell (Yellow)"; - sprite = "SSHLI1"; - width = 24; - height = 40; - } - 109 - { - title = "Skim"; - sprite = "SKIMA1"; - width = 16; - height = 24; - } - 113 - { - title = "Jet Jaw"; - sprite = "JJAWA3A7"; - width = 12; - height = 20; - } - 126 - { - title = "Crushstacean"; - sprite = "CRABA0"; - width = 24; - height = 32; - flags8text = "[8] Move left from spawn"; - } - 138 - { - title = "Banpyura"; - sprite = "CR2BA0"; - width = 24; - height = 32; - flags8text = "[8] Move left from spawn"; - } - 117 - { - title = "Robo-Hood"; - sprite = "ARCHA1"; - width = 24; - height = 32; - } - 118 - { - title = "Lance-a-Bot"; - sprite = "CBFSA1"; - width = 32; - height = 72; - } - 1113 - { - title = "Suspicious Lance-a-Bot Statue"; - sprite = "CBBSA1"; - width = 32; - height = 72; - } - 119 - { - title = "Egg Guard"; - sprite = "ESHIA1"; - width = 16; - height = 48; - flags1text = "[1] 90 degrees counter-clockwise"; - flags4text = "[4] 90 degrees clockwise"; - flags8text = "[8] Double speed"; - } - 115 - { - title = "Bird Aircraft Strike Hazard"; - sprite = "VLTRF1"; - width = 12; - height = 24; - } - 120 - { - title = "Green Snapper"; - sprite = "GSNPA1"; - width = 24; - height = 24; - } - 121 - { - title = "Minus"; - sprite = "MNUSA0"; - width = 24; - height = 32; - } - 134 - { - title = "Canarivore"; - sprite = "CANAA0"; - width = 12; - height = 80; - hangs = 1; - } - 123 - { - title = "Unidus"; - sprite = "UNIDA1"; - width = 18; - height = 36; - } - 135 - { - title = "Pterabyte Spawner"; - sprite = "PTERA2A8"; - width = 16; - height = 16; - parametertext = "No. Pterabytes"; - } - 136 - { - title = "Pyre Fly"; - sprite = "PYREA0"; - width = 24; - height = 34; - flags8text = "[8] Start on fire"; - } - 137 - { - title = "Dragonbomber"; - sprite = "DRABA1"; - width = 28; - height = 48; - } - 105 - { - title = "Jetty-Syn Bomber"; - sprite = "JETBB1"; - width = 20; - height = 50; - flags8text = "[8] Cannot move"; - } - 106 - { - title = "Jetty-Syn Gunner"; - sprite = "JETGB1"; - width = 20; - height = 48; - flags8text = "[8] Cannot move"; - } - 112 - { - title = "Spincushion"; - sprite = "SHRPA1"; - width = 16; - height = 24; - } - 114 - { - title = "Snailer"; - sprite = "SNLRA3A7"; - width = 24; - height = 48; - } - 129 - { - title = "Penguinator"; - sprite = "PENGA1"; - width = 24; - height = 32; - } - 130 - { - title = "Pophat"; - sprite = "POPHA1"; - width = 24; - height = 32; - } - 107 - { - title = "Crawla Commander"; - sprite = "CCOMA1"; - width = 16; - height = 32; - } - 131 - { - title = "Spinbobert"; - sprite = "SBOBB0"; - width = 32; - height = 32; - } - 132 - { - title = "Cacolantern"; - sprite = "CACOA0"; - width = 32; - height = 32; - flags8text = "[8] Cannot move"; - } - 133 - { - title = "Hangster"; - sprite = "HBATC1"; - width = 24; - height = 24; - hangs = 1; - } - 127 - { - title = "Hive Elemental"; - sprite = "HIVEA0"; - width = 32; - height = 80; - parametertext = "No. bees"; - } - 128 - { - title = "Bumblebore"; - sprite = "BUMBA1"; - width = 16; - height = 32; - } - 124 - { - title = "Buggle"; - sprite = "BBUZA1"; - width = 20; - height = 24; - } - 116 - { - title = "Pointy"; - sprite = "PNTYA1"; - width = 8; - height = 16; - } - } - - bosses - { - color = 8; // Dark_Gray - arrow = 1; - title = "Bosses"; - - 200 - { - title = "Egg Mobile"; - sprite = "EGGMA1"; - width = 24; - height = 76; - flags4text = "[4] End level on death"; - flags8text = "[8] Alternate laser attack"; - } - 201 - { - title = "Egg Slimer"; - sprite = "EGGNA1"; - width = 24; - height = 76; - flags4text = "[4] End level on death"; - flags8text = "[8] Speed up when hit"; - } - 202 - { - title = "Sea Egg"; - sprite = "EGGOA1"; - width = 32; - height = 116; - flags4text = "[4] End level on death"; - } - 203 - { - title = "Egg Colosseum"; - sprite = "EGGPA1"; - width = 24; - height = 76; - flags4text = "[4] End level on death"; - } - 204 - { - title = "Fang"; - sprite = "FANGA1"; - width = 24; - height = 60; - flags1text = "[1] Grayscale mode"; - flags4text = "[4] End level on death"; - } - 206 - { - title = "Brak Eggman (Old)"; - sprite = "BRAKB1"; - width = 48; - height = 160; - flags4text = "[4] End level on death"; - } - 207 - { - title = "Metal Sonic (Race)"; - sprite = "METLI1"; - width = 16; - height = 48; - flags1text = "[1] Grayscale mode"; - } - 208 - { - title = "Metal Sonic (Battle)"; - sprite = "METLC1"; - width = 16; - height = 48; - flags1text = "[1] Grayscale mode"; - flags4text = "[4] End level on death"; - } - 209 - { - title = "Brak Eggman"; - sprite = "BRAK01"; - width = 48; - height = 160; - flags1text = "[1] No origin-fling death"; - flags4text = "[4] End level on death"; - flags8text = "[8] Electric barrier"; - } - 290 - { - arrow = 0; - title = "Boss Escape Point"; - width = 8; - height = 16; - sprite = "internal:eggmanend"; - } - 291 - { - arrow = 0; - title = "Egg Capsule Center"; - width = 8; - height = 16; - sprite = "internal:capsule"; - } - 292 - { - arrow = 0; - title = "Boss Waypoint"; - width = 8; - height = 16; - flags8text = "[8] Sea Egg shooting point"; - sprite = "internal:eggmanway"; - angletext = "No. (Sea Egg)"; - flagsvaluetext = "No. (Brak)"; - parametertext = "Next"; - } - 293 - { - title = "Metal Sonic Gather Point"; - sprite = "internal:metal"; - width = 8; - height = 16; - } - 294 - { - title = "Fang Waypoint"; - flags8text = "[8] Center waypoint"; - sprite = "internal:eggmanway"; - width = 8; - height = 16; - } - } - - rings - { - color = 14; // Yellow - title = "Rings and Weapon Panels"; - width = 24; - height = 24; - flags8height = 24; - flags8text = "[8] Float"; - sprite = "RINGA0"; - - 300 - { - title = "Ring"; - sprite = "RINGA0"; - width = 16; - } - 301 - { - title = "Bounce Ring"; - sprite = "internal:RNGBA0"; - } - 302 - { - title = "Rail Ring"; - sprite = "internal:RNGRA0"; - } - 303 - { - title = "Infinity Ring"; - sprite = "internal:RNGIA0"; - } - 304 - { - title = "Automatic Ring"; - sprite = "internal:RNGAA0"; - } - 305 - { - title = "Explosion Ring"; - sprite = "internal:RNGEA0"; - } - 306 - { - title = "Scatter Ring"; - sprite = "internal:RNGSA0"; - } - 307 - { - title = "Grenade Ring"; - sprite = "internal:RNGGA0"; - } - 308 - { - title = "CTF Team Ring (Red)"; - sprite = "internal:RRNGA0"; - width = 16; - } - 309 - { - title = "CTF Team Ring (Blue)"; - sprite = "internal:BRNGA0"; - width = 16; - } - 330 - { - title = "Bounce Ring Panel"; - sprite = "internal:PIKBA0"; - } - 331 - { - title = "Rail Ring Panel"; - sprite = "internal:PIKRA0"; - } - 332 - { - title = "Automatic Ring Panel"; - sprite = "internal:PIKAA0"; - } - 333 - { - title = "Explosion Ring Panel"; - sprite = "internal:PIKEA0"; - } - 334 - { - title = "Scatter Ring Panel"; - sprite = "internal:PIKSA0"; - } - 335 - { - title = "Grenade Ring Panel"; - sprite = "internal:PIKGA0"; - } - } - - collectibles - { - color = 10; // Light_Green - title = "Other Collectibles"; - width = 16; - height = 32; - sort = 1; - sprite = "CEMGA0"; - - 310 - { - title = "CTF Red Flag"; - sprite = "RFLGA0"; - width = 24; - height = 64; - } - 311 - { - title = "CTF Blue Flag"; - sprite = "BFLGA0"; - width = 24; - height = 64; - } - 312 - { - title = "Emerald Token"; - sprite = "TOKEA0"; - width = 16; - height = 32; - flags8height = 24; - flags8text = "[8] Float"; - } - 313 - { - title = "Chaos Emerald 1 (Green)"; - sprite = "CEMGA0"; - } - 314 - { - title = "Chaos Emerald 2 (Purple)"; - sprite = "CEMGB0"; - } - 315 - { - title = "Chaos Emerald 3 (Blue)"; - sprite = "CEMGC0"; - } - 316 - { - title = "Chaos Emerald 4 (Cyan)"; - sprite = "CEMGD0"; - } - 317 - { - title = "Chaos Emerald 5 (Orange)"; - sprite = "CEMGE0"; - } - 318 - { - title = "Chaos Emerald 6 (Red)"; - sprite = "CEMGF0"; - } - 319 - { - title = "Chaos Emerald 7 (Gray)"; - sprite = "CEMGG0"; - } - 320 - { - title = "Emerald Hunt Location"; - sprite = "SHRDA0"; - } - 321 - { - title = "Match Chaos Emerald Spawn"; - sprite = "CEMGA0"; - flags8height = 24; - flags8text = "[8] Float"; - } - 322 - { - title = "Emblem"; - sprite = "EMBMA0"; - width = 16; - height = 30; - flags8height = 24; - flags8text = "[8] Float"; - angletext = "Tag"; - } - } - - boxes - { - color = 7; // Gray - blocking = 2; - title = "Monitors"; - width = 18; - height = 40; - flags1text = "[1] Run Linedef Executor on pop"; - flags4text = "[4] Random (Strong)"; - flags8text = "[8] Random (Weak)"; - - 400 - { - title = "Super Ring (10 Rings)"; - sprite = "TVRIA0"; - } - 401 - { - title = "Pity Shield"; - sprite = "TVPIA0"; - } - 402 - { - title = "Attraction Shield"; - sprite = "TVATA0"; - } - 403 - { - title = "Force Shield"; - sprite = "TVFOA0"; - } - 404 - { - title = "Armageddon Shield"; - sprite = "TVARA0"; - } - 405 - { - title = "Whirlwind Shield"; - sprite = "TVWWA0"; - } - 406 - { - title = "Elemental Shield"; - sprite = "TVELA0"; - } - 407 - { - title = "Super Sneakers"; - sprite = "TVSSA0"; - } - 408 - { - title = "Invincibility"; - sprite = "TVIVA0"; - } - 409 - { - title = "Extra Life"; - sprite = "TV1UA0"; - flags4text = "[4] Random (Strong) / 10k points"; - flags8text = "[8] Random (Weak) / 10k points"; - } - 410 - { - title = "Eggman"; - sprite = "TVEGA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 411 - { - title = "Teleporter"; - sprite = "TVMXA0"; - } - 413 - { - title = "Gravity Boots"; - sprite = "TVGVA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 414 - { - title = "CTF Team Ring Monitor (Red)"; - sprite = "TRRIA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 415 - { - title = "CTF Team Ring Monitor (Blue)"; - sprite = "TBRIA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 416 - { - title = "Recycler"; - sprite = "TVRCA0"; - } - 418 - { - title = "Score (1,000 Points)"; - sprite = "TV1KA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 419 - { - title = "Score (10,000 Points)"; - sprite = "TVTKA0"; - flags4text = "[4] Special"; - flags8text = "[8] Ambush"; - } - 420 - { - title = "Flame Shield"; - sprite = "TVFLA0"; - } - 421 - { - title = "Water Shield"; - sprite = "TVBBA0"; - } - 422 - { - title = "Lightning Shield"; - sprite = "TVZPA0"; - } - } - - boxes2 - { - color = 18; // Gold - blocking = 2; - title = "Monitors (Respawning)"; - width = 20; - height = 44; - flags1text = "[1] Run Linedef Executor on pop"; - - 431 - { - title = "Pity Shield (Respawn)"; - sprite = "TVPIB0"; - } - 432 - { - title = "Attraction Shield (Respawn)"; - sprite = "TVATB0"; - } - 433 - { - title = "Force Shield (Respawn)"; - sprite = "TVFOB0"; - } - 434 - { - title = "Armageddon Shield (Respawn)"; - sprite = "TVARB0"; - } - 435 - { - title = "Whirlwind Shield (Respawn)"; - sprite = "TVWWB0"; - } - 436 - { - title = "Elemental Shield (Respawn)"; - sprite = "TVELB0"; - } - 437 - { - title = "Super Sneakers (Respawn)"; - sprite = "TVSSB0"; - } - 438 - { - title = "Invincibility (Respawn)"; - sprite = "TVIVB0"; - } - 440 - { - title = "Eggman (Respawn)"; - sprite = "TVEGB0"; - } - 443 - { - title = "Gravity Boots (Respawn)"; - sprite = "TVGVB0"; - } - 450 - { - title = "Flame Shield (Respawn)"; - sprite = "TVFLB0"; - } - 451 - { - title = "Water Shield (Respawn)"; - sprite = "TVBBB0"; - } - 452 - { - title = "Lightning Shield (Respawn)"; - sprite = "TVZPB0"; - } - } - - generic - { - color = 11; // Light_Cyan - title = "Generic Items & Hazards"; - - 500 - { - title = "Air Bubble Patch"; - sprite = "BUBLE0"; - width = 8; - height = 16; - flags8text = "[8] No distance check"; - } - 501 - { - title = "Signpost"; - sprite = "SIGND0"; - width = 8; - height = 32; - } - 502 - { - arrow = 1; - title = "Star Post"; - sprite = "STPTA0M0"; - width = 64; - height = 128; - angletext = "Angle/Order"; - } - 520 - { - title = "Bomb Sphere"; - sprite = "SPHRD0"; - width = 16; - height = 24; - flags8height = 24; - flags8text = "[8] Float"; - unflippable = true; - } - 521 - { - title = "Spikeball"; - sprite = "SPIKA0"; - width = 12; - height = 8; - flags8height = 24; - flags8text = "[8] Float"; - } - 522 - { - title = "Wall Spike"; - sprite = "WSPKALAR"; - width = 16; - height = 14; - flags1text = "[1] Start retracted"; - flags4text = "[4] Retractable"; - flags8text = "[8] Intangible"; - parametertext = "Initial delay"; - } - 523 - { - title = "Spike"; - sprite = "USPKA0"; - width = 8; - height = 32; - flags1text = "[1] Start retracted"; - flags4text = "[4] Retractable"; - flags8text = "[8] Intangible"; - angletext = "Retraction interval"; - parametertext = "Initial delay"; - } - 1130 - { - title = "Small Mace"; - sprite = "SMCEA0"; - width = 17; - height = 34; - } - 1131 - { - title = "Big Mace"; - sprite = "BMCEA0"; - width = 34; - height = 68; - } - 1136 - { - title = "Small Fireball"; - sprite = "SFBRA0"; - width = 17; - height = 34; - } - 1137 - { - title = "Large Fireball"; - sprite = "BFBRA0"; - width = 34; - height = 68; - } - } - - springs - { - color = 12; // Light_Red - title = "Springs and Fans"; - width = 20; - height = 16; - sprite = "RSPRD2"; - - 540 - { - title = "Fan"; - sprite = "FANSA0D0"; - width = 16; - height = 8; - flags4text = "[4] Invisible"; - flags8text = "[8] No distance check"; - angletext = "Lift height"; - } - 541 - { - title = "Gas Jet"; - sprite = "STEMD0"; - flags8text = "[8] No sounds"; - width = 32; - } - 542 - { - title = "Bumper"; - sprite = "BUMPA0"; - width = 32; - height = 64; - angletext = "Strength"; - } - 543 - { - title = "Balloon"; - sprite = "BLONA0"; - width = 32; - height = 64; - flags8text = "[8] Respawn"; - angletext = "Color"; - } - 550 - { - title = "Yellow Spring"; - sprite = "SPRYA0"; - } - 551 - { - title = "Red Spring"; - sprite = "SPRRA0"; - } - 552 - { - title = "Blue Spring"; - sprite = "SPRBA0"; - } - 555 - { - arrow = 1; - title = "Diagonal Yellow Spring"; - sprite = "YSPRD2"; - width = 16; - flags4text = "[4] Ignore gravity"; - flags8text = "[8] Rotate 22.5° CCW"; - } - 556 - { - arrow = 1; - title = "Diagonal Red Spring"; - sprite = "RSPRD2"; - width = 16; - flags4text = "[4] Ignore gravity"; - flags8text = "[8] Rotate 22.5° CCW"; - } - 557 - { - arrow = 1; - title = "Diagonal Blue Spring"; - sprite = "BSPRD2"; - width = 16; - flags4text = "[4] Ignore gravity"; - flags8text = "[8] Rotate 22.5° CCW"; - } - 558 - { - arrow = 1; - title = "Horizontal Yellow Spring"; - sprite = "SSWYD2D8"; - flags8height = 16; - flags8text = "[8] Float"; - width = 16; - height = 32; - } - 559 - { - arrow = 1; - title = "Horizontal Red Spring"; - sprite = "SSWRD2D8"; - flags8height = 16; - flags8text = "[8] Float"; - width = 16; - height = 32; - } - 560 - { - arrow = 1; - title = "Horizontal Blue Spring"; - sprite = "SSWBD2D8"; - flags8height = 16; - flags8text = "[8] Float"; - width = 16; - height = 32; - } - 1134 - { - title = "Yellow Spring Ball"; - sprite = "YSPBA0"; - width = 17; - height = 34; - } - 1135 - { - title = "Red Spring Ball"; - sprite = "RSPBA0"; - width = 17; - height = 34; - } - 544 - { - arrow = 1; - title = "Yellow Boost Panel"; - sprite = "BSTYA0"; - flags8text = "[8] Force spin"; - width = 28; - height = 2; - } - 545 - { - arrow = 1; - title = "Red Boost Panel"; - sprite = "BSTRA0"; - flags8text = "[8] Force spin"; - width = 28; - height = 2; - } - } - - patterns - { - color = 5; // Magenta - arrow = 1; - title = "Special Placement Patterns"; - width = 16; - height = 384; - sprite = "RINGA0"; - - 600 - { - arrow = 0; - title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; - } - 601 - { - arrow = 0; - title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; - height = 1024; - } - 602 - { - title = "5 Diagonal Rings (Yellow Spring)"; - sprite = "RINGA0"; - height = 32; - } - 603 - { - title = "10 Diagonal Rings (Red Spring)"; - sprite = "RINGA0"; - height = 32; - } - 604 - { - title = "Circle of Rings"; - sprite = "RINGA0"; - width = 96; - height = 192; - unflippable = true; - centerHitbox = true; - } - 605 - { - title = "Circle of Rings (Big)"; - sprite = "RINGA0"; - width = 192; - unflippable = true; - centerHitbox = true; - } - 606 - { - title = "Circle of Blue Spheres"; - sprite = "SPHRA0"; - width = 96; - height = 192; - unflippable = true; - centerHitbox = true; - } - 607 - { - title = "Circle of Blue Spheres (Big)"; - sprite = "SPHRA0"; - width = 192; - unflippable = true; - centerHitbox = true; - } - 608 - { - title = "Circle of Rings and Spheres"; - sprite = "SPHRA0"; - width = 96; - height = 192; - unflippable = true; - centerHitbox = true; - } - 609 - { - title = "Circle of Rings and Spheres (Big)"; - sprite = "SPHRA0"; - width = 192; - unflippable = true; - centerHitbox = true; - } - } - - invisible - { - color = 15; // White - title = "Misc. Invisible"; - width = 8; - height = 16; - sprite = "UNKNA0"; - - 700 - { - title = "Water Ambience A (Large)"; - sprite = "internal:ambiance"; - } - - 701 - { - title = "Water Ambience B (Large)"; - sprite = "internal:ambiance"; - } - - 702 - { - title = "Water Ambience C (Medium)"; - sprite = "internal:ambiance"; - } - - 703 - { - title = "Water Ambience D (Medium)"; - sprite = "internal:ambiance"; - } - - 704 - { - title = "Water Ambience E (Small)"; - sprite = "internal:ambiance"; - } - - 705 - { - title = "Water Ambience F (Small)"; - sprite = "internal:ambiance"; - } - - 706 - { - title = "Water Ambience G (Extra Large)"; - sprite = "internal:ambiance"; - } - - 707 - { - title = "Water Ambience H (Extra Large)"; - sprite = "internal:ambiance"; - } - - 708 - { - title = "Disco Ambience"; - sprite = "internal:ambiance"; - } - - 709 - { - title = "Volcano Ambience"; - sprite = "internal:ambiance"; - } - - 710 - { - title = "Machine Ambience"; - sprite = "internal:ambiance"; - } - - 750 - { - title = "Slope Vertex"; - sprite = "internal:vertexslope"; - angletext = "Tag"; - } - - 751 - { - arrow = 1; - title = "Teleport Destination"; - sprite = "internal:tele"; - } - - 752 - { - arrow = 1; - title = "Alternate View Point"; - sprite = "internal:view"; - } - - 753 - { - title = "Zoom Tube Waypoint"; - sprite = "internal:zoom"; - angletext = "Order"; - } - - 754 - { - title = "Push Point"; - flags4text = "[4] Fades using XY"; - flags8text = "[8] Push using XYZ"; - sprite = "GWLGA0"; - angletext = "Radius"; - } - 755 - { - title = "Pull Point"; - flags4text = "[4] Fades using XY"; - flags8text = "[8] Pull using XYZ"; - sprite = "GWLRA0"; - angletext = "Radius"; - } - 756 - { - title = "Blast Linedef Executor"; - sprite = "TOADA0"; - width = 32; - height = 16; - } - 757 - { - title = "Fan Particle Generator"; - sprite = "PRTLA0"; - width = 8; - height = 16; - angletext = "Tag"; - } - 758 - { - title = "Object Angle Anchor"; - sprite = "internal:view"; - } - 760 - { - title = "PolyObject Anchor"; - sprite = "internal:polyanchor"; - angletext = "ID"; - } - - 761 - { - title = "PolyObject Spawn Point"; - sprite = "internal:polycenter"; - angletext = "ID"; - } - - 762 - { - title = "PolyObject Spawn Point (Crush)"; - sprite = "internal:polycentercrush"; - angletext = "ID"; - } - 780 - { - title = "Skybox View Point"; - sprite = "internal:skyb"; - flags4text = "[4] In-map centerpoint"; - parametertext = "ID"; - } - } - - greenflower - { - color = 10; // Green - title = "Greenflower"; - - 800 - { - title = "GFZ Flower"; - sprite = "FWR1A0"; - width = 16; - height = 40; - } - 801 - { - title = "Sunflower"; - sprite = "FWR2A0"; - width = 16; - height = 96; - } - 802 - { - title = "Budding Flower"; - sprite = "FWR3A0"; - width = 8; - height = 32; - } - 803 - { - title = "Blueberry Bush"; - sprite = "BUS3A0"; - width = 16; - height = 32; - } - 804 - { - title = "Berry Bush"; - sprite = "BUS1A0"; - width = 16; - height = 32; - } - 805 - { - title = "Bush"; - sprite = "BUS2A0"; - width = 16; - height = 32; - } - 806 - { - title = "GFZ Tree"; - sprite = "TRE1A0"; - width = 20; - height = 128; - } - 807 - { - title = "GFZ Berry Tree"; - sprite = "TRE1B0"; - width = 20; - height = 128; - } - 808 - { - title = "GFZ Cherry Tree"; - sprite = "TRE1C0"; - width = 20; - height = 128; - } - 809 - { - title = "Checkered Tree"; - sprite = "TRE2A0"; - width = 20; - height = 200; - } - 810 - { - title = "Checkered Tree (Sunset)"; - sprite = "TRE2B0"; - width = 20; - height = 200; - } - 811 - { - title = "Polygon Tree"; - sprite = "TRE4A0"; - width = 20; - height = 200; - } - 812 - { - title = "Bush Tree"; - sprite = "TRE5A0"; - width = 20; - height = 200; - } - 813 - { - title = "Red Bush Tree"; - sprite = "TRE5B0"; - width = 20; - height = 200; - } - } - - technohill - { - color = 10; // Green - title = "Techno Hill"; - - 900 - { - title = "THZ Steam Flower"; - sprite = "THZPA0"; - width = 8; - height = 32; - } - 901 - { - title = "Alarm"; - sprite = "ALRMA0"; - width = 8; - height = 16; - hangs = 1; - } - 902 - { - title = "THZ Spin Flower (Red)"; - sprite = "FWR5A0"; - width = 16; - height = 64; - } - 903 - { - title = "THZ Spin Flower (Yellow)"; - sprite = "FWR6A0"; - width = 16; - height = 64; - } - 904 - { - arrow = 1; - title = "Whistlebush"; - sprite = "THZTA0"; - width = 16; - height = 64; - } - } - - deepsea - { - color = 10; // Green - title = "Deep Sea"; - - 1000 - { - arrow = 1; - blocking = 2; - title = "Gargoyle"; - sprite = "GARGA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1009 - { - arrow = 1; - blocking = 2; - title = "Gargoyle (Big)"; - sprite = "GARGB1"; - width = 32; - height = 80; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1001 - { - title = "Seaweed"; - sprite = "SEWEA0"; - width = 24; - height = 56; - } - 1002 - { - title = "Dripping Water"; - sprite = "DRIPD0"; - width = 8; - height = 16; - hangs = 1; - angletext = "Dripping interval"; - } - 1003 - { - title = "Coral (Green)"; - sprite = "CORLA0"; - width = 29; - height = 40; - } - 1004 - { - title = "Coral (Red)"; - sprite = "CORLB0"; - width = 30; - height = 53; - } - 1005 - { - title = "Coral (Orange)"; - sprite = "CORLC0"; - width = 28; - height = 41; - } - 1006 - { - title = "Blue Crystal"; - sprite = "BCRYA1"; - width = 8; - height = 16; - } - 1007 - { - title = "Kelp"; - sprite = "KELPA0"; - width = 16; - height = 292; - flags4text = "[4] Double size"; - } - 1008 - { - title = "Stalagmite (DSZ1)"; - sprite = "DSTGA0"; - width = 8; - height = 116; - flags4text = "[4] Double size"; - } - 1010 - { - arrow = 1; - title = "Light Beam"; - sprite = "LIBEARAL"; - width = 16; - height = 16; - } - 1011 - { - title = "Stalagmite (DSZ2)"; - sprite = "DSTGA0"; - width = 8; - height = 116; - flags4text = "[4] Double size"; - } - 1012 - { - arrow = 1; - title = "Big Floating Mine"; - width = 28; - height = 56; - sprite = "BMNEA1"; - } - 1013 - { - title = "Animated Kelp"; - sprite = "ALGAA0"; - width = 48; - height = 120; - } - 1014 - { - title = "Large Coral (Brown)"; - sprite = "CORLD0"; - width = 56; - height = 112; - } - 1015 - { - title = "Large Coral (Beige)"; - sprite = "CORLE0"; - width = 56; - height = 112; - } - } - - castleeggman - { - color = 10; // Green - title = "Castle Eggman"; - - 1100 - { - title = "Chain (Decorative)"; - sprite = "CHANA0"; - width = 4; - height = 128; - hangs = 1; - } - 1101 - { - title = "Torch"; - sprite = "FLAMA0E0"; - width = 8; - height = 32; - flags1text = "[1] Add corona"; - } - 1102 - { - arrow = 1; - blocking = 2; - title = "Eggman Statue"; - sprite = "ESTAA1"; - width = 32; - height = 240; - flags1text = "[1] Solid gold"; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1103 - { - title = "CEZ Flower"; - sprite = "FWR4A0"; - width = 16; - height = 40; - } - 1104 - { - title = "Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - flags4text = "[4] No sounds"; - flags8text = "[8] Double size"; - angletext = "Tag"; - } - 1105 - { - title = "Chain with Maces Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - flags4text = "[4] No sounds"; - flags8text = "[8] Double size"; - angletext = "Tag"; - } - 1106 - { - title = "Chained Spring Spawnpoint"; - sprite = "YSPBA0"; - width = 17; - height = 34; - flags4text = "[4] No sounds"; - flags8text = "[8] Red spring"; - angletext = "Tag"; - } - 1107 - { - title = "Chain Spawnpoint"; - sprite = "BMCHA0"; - width = 17; - height = 34; - flags8text = "[8] Double size"; - angletext = "Tag"; - } - 1108 - { - arrow = 1; - title = "Hidden Chain Spawnpoint"; - sprite = "internal:chain3"; - width = 17; - height = 34; - flags8text = "[8] Double size"; - } - 1109 - { - title = "Firebar Spawnpoint"; - sprite = "BFBRA0"; - width = 17; - height = 34; - flags4text = "[4] No sounds"; - flags8text = "[8] Double size"; - angletext = "Tag"; - } - 1110 - { - title = "Custom Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - flags4text = "[4] No sounds"; - angletext = "Tag"; - } - 1111 - { - arrow = 1; - blocking = 2; - title = "Crawla Statue"; - sprite = "CSTAA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1112 - { - arrow = 1; - blocking = 2; - title = "Lance-a-Bot Statue"; - sprite = "CBBSA1"; - width = 32; - height = 72; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1114 - { - title = "Pine Tree"; - sprite = "PINEA0"; - width = 16; - height = 628; - } - 1115 - { - title = "CEZ Shrub (Small)"; - sprite = "CEZBA0"; - width = 16; - height = 24; - } - 1116 - { - title = "CEZ Shrub (Large)"; - sprite = "CEZBB0"; - width = 32; - height = 48; - } - 1117 - { - arrow = 1; - title = "Pole Banner (Red)"; - sprite = "BANRA0"; - width = 40; - height = 224; - } - 1118 - { - arrow = 1; - title = "Pole Banner (Blue)"; - sprite = "BANRA0"; - width = 40; - height = 224; - } - 1119 - { - title = "Candle"; - sprite = "CNDLA0"; - width = 8; - height = 48; - flags1text = "[1] Add corona"; - } - 1120 - { - title = "Candle Pricket"; - sprite = "CNDLB0"; - width = 8; - height = 176; - flags1text = "[1] Add corona"; - } - 1121 - { - title = "Flame Holder"; - sprite = "FLMHA0"; - width = 24; - height = 80; - flags1text = "[1] Add corona"; - flags4text = "[4] No flame"; - } - 1122 - { - title = "Fire Torch"; - sprite = "CTRCA0"; - width = 16; - height = 80; - } - 1123 - { - title = "Cannonball Launcher"; - sprite = "internal:cannonball"; - width = 8; - height = 16; - } - 1124 - { - blocking = 2; - title = "Cannonball"; - sprite = "CBLLA0"; - width = 20; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1125 - { - title = "Brambles"; - sprite = "CABRALAR"; - width = 48; - height = 32; - } - 1126 - { - title = "Invisible Lockon Object"; - sprite = "LCKNC0"; - width = 16; - height = 32; - } - 1127 - { - title = "Spectator Eggrobo"; - sprite = "EGR1A1"; - width = 20; - height = 72; - } - 1128 - { - arrow = 1; - title = "Waving Flag (Red)"; - sprite = "CFLGA0"; - width = 8; - height = 208; - } - 1129 - { - arrow = 1; - title = "Waving Flag (Blue)"; - sprite = "CFLGA0"; - width = 8; - height = 208; - } - } - - aridcanyon - { - color = 10; // Green - title = "Arid Canyon"; - - 1200 - { - title = "Tumbleweed (Big)"; - sprite = "BTBLA0"; - width = 24; - height = 48; - flags8text = "[8] Moves perpetually"; - } - 1201 - { - title = "Tumbleweed (Small)"; - sprite = "STBLA0"; - width = 12; - height = 24; - flags8text = "[8] Moves perpetually"; - } - 1202 - { - arrow = 1; - title = "Rock Spawner"; - sprite = "ROIAA0"; - width = 8; - height = 16; - angletext = "Tag"; - } - 1203 - { - title = "Tiny Red Flower Cactus"; - sprite = "CACTA0"; - width = 13; - height = 24; - } - 1204 - { - title = "Small Red Flower Cactus"; - sprite = "CACTB0"; - width = 15; - height = 52; - } - 1205 - { - title = "Tiny Blue Flower Cactus"; - sprite = "CACTC0"; - width = 13; - height = 24; - } - 1206 - { - title = "Small Blue Flower Cactus"; - sprite = "CACTD0"; - width = 15; - height = 52; - } - 1207 - { - title = "Prickly Pear"; - sprite = "CACTE0"; - width = 32; - height = 96; - } - 1208 - { - title = "Barrel Cactus"; - sprite = "CACTF0"; - width = 20; - height = 128; - } - 1209 - { - title = "Tall Barrel Cactus"; - sprite = "CACTG0"; - width = 24; - height = 224; - } - 1210 - { - title = "Armed Cactus"; - sprite = "CACTH0"; - width = 24; - height = 256; - } - 1211 - { - title = "Ball Cactus"; - sprite = "CACTI0"; - width = 48; - height = 96; - } - 1212 - { - title = "Caution Sign"; - sprite = "WWSGAR"; - width = 22; - height = 64; - } - 1213 - { - title = "Cacti Sign"; - sprite = "WWS2AR"; - width = 22; - height = 64; - } - 1214 - { - title = "Sharp Turn Sign"; - sprite = "WWS3ALAR"; - width = 16; - height = 192; - } - 1215 - { - title = "Mine Oil Lamp"; - sprite = "OILLA0"; - width = 22; - height = 64; - hangs = 1; - } - 1216 - { - title = "TNT Barrel"; - sprite = "BARRA1"; - width = 24; - height = 63; - } - 1217 - { - title = "TNT Proximity Shell"; - sprite = "REMTA0"; - width = 64; - height = 40; - } - 1218 - { - title = "Dust Devil"; - sprite = "TAZDCR"; - width = 80; - height = 416; - } - 1219 - { - title = "Minecart Spawner"; - sprite = "MCRTCLFR"; - width = 22; - height = 32; - } - 1220 - { - title = "Minecart Stopper"; - sprite = "MCRTIR"; - width = 32; - height = 32; - } - 1221 - { - title = "Minecart Saloon Door"; - sprite = "SALDARAL"; - width = 96; - height = 160; - flags8text = "[8] Allow non-minecart players"; - } - 1222 - { - title = "Train Cameo Spawner"; - sprite = "TRAEBRBL"; - width = 28; - height = 32; - } - 1223 - { - title = "Train Dust Spawner"; - sprite = "ADSTA0"; - width = 4; - height = 4; - } - 1224 - { - title = "Train Steam Spawner"; - sprite = "STEAA0"; - width = 4; - height = 4; - } - 1229 - { - title = "Minecart Switch Point"; - sprite = "internal:zoom"; - width = 8; - height = 16; - flags8text = "[8] Enable switching"; - } - 1230 - { - title = "Tiny Cactus"; - sprite = "CACTJ0"; - width = 13; - height = 28; - } - 1231 - { - title = "Small Cactus"; - sprite = "CACTK0"; - width = 15; - height = 60; - } - } - - redvolcano - { - color = 10; // Green - title = "Red Volcano"; - - 1300 - { - arrow = 1; - title = "Flame Jet (Horizontal)"; - sprite = "internal:flameh"; - width = 16; - height = 40; - flags8text = "[8] Waves vertically"; - angletext = "On/Off time"; - parametertext = "Strength"; - } - 1301 - { - title = "Flame Jet (Vertical)"; - sprite = "internal:flamev"; - width = 16; - height = 40; - flags8text = "[8] Shoot downwards"; - angletext = "On/Off time"; - parametertext = "Strength"; - } - 1302 - { - title = "Spinning Flame Jet (Counter-Clockwise)"; - sprite = "internal:flame2"; - width = 16; - height = 24; - } - 1303 - { - title = "Spinning Flame Jet (Clockwise)"; - sprite = "internal:flame1"; - width = 16; - height = 24; - } - 1304 - { - title = "Lavafall"; - sprite = "LFALF0"; - width = 30; - height = 32; - angletext = "Initial delay"; - flags8text = "[8] Double size"; - } - 1305 - { - title = "Rollout Rock"; - sprite = "PUMIA1A5"; - width = 30; - height = 60; - flags8text = "[8] Non-buoyant"; - } - 1306 - { - title = "Big Fern"; - sprite = "JPLAB0"; - width = 32; - height = 48; - } - 1307 - { - title = "Jungle Palm"; - sprite = "JPLAC0"; - width = 32; - height = 48; - } - 1308 - { - title = "Torch Flower"; - sprite = "TFLOA0"; - width = 14; - height = 110; - } - 1309 - { - title = "RVZ1 Wall Vine (Long)"; - sprite = "WVINALAR"; - width = 1; - height = 288; - } - 1310 - { - title = "RVZ1 Wall Vine (Short)"; - sprite = "WVINBLBR"; - width = 1; - height = 288; - } - } - - botanicserenity - { - color = 10; // Green - title = "Botanic Serenity"; - width = 16; - height = 32; - sprite = "BSZ1A0"; - 1400 - { - title = "Tall Flower (Red)"; - sprite = "BSZ1A0"; - } - 1401 - { - title = "Tall Flower (Purple)"; - sprite = "BSZ1B0"; - } - 1402 - { - title = "Tall Flower (Blue)"; - sprite = "BSZ1C0"; - } - 1403 - { - title = "Tall Flower (Cyan)"; - sprite = "BSZ1D0"; - } - 1404 - { - title = "Tall Flower (Yellow)"; - sprite = "BSZ1E0"; - } - 1405 - { - title = "Tall Flower (Orange)"; - sprite = "BSZ1F0"; - } - 1410 - { - title = "Medium Flower (Red)"; - sprite = "BSZ2A0"; - } - 1411 - { - title = "Medium Flower (Purple)"; - sprite = "BSZ2B0"; - } - 1412 - { - title = "Medium Flower (Blue)"; - sprite = "BSZ2C0"; - } - 1413 - { - title = "Medium Flower (Cyan)"; - sprite = "BSZ2D0"; - } - 1414 - { - title = "Medium Flower (Yellow)"; - sprite = "BSZ2E0"; - } - 1415 - { - title = "Medium Flower (Orange)"; - sprite = "BSZ2F0"; - } - 1420 - { - title = "Short Flower (Red)"; - sprite = "BSZ3A0"; - } - 1421 - { - title = "Short Flower (Purple)"; - sprite = "BSZ3B0"; - } - 1422 - { - title = "Short Flower (Blue)"; - sprite = "BSZ3C0"; - } - 1423 - { - title = "Short Flower (Cyan)"; - sprite = "BSZ3D0"; - } - 1424 - { - title = "Short Flower (Yellow)"; - sprite = "BSZ3E0"; - } - 1425 - { - title = "Short Flower (Orange)"; - sprite = "BSZ3F0"; - } - 1430 - { - title = "Tulip (Red)"; - sprite = "BST1A0"; - } - 1431 - { - title = "Tulip (Purple)"; - sprite = "BST2A0"; - } - 1432 - { - title = "Tulip (Blue)"; - sprite = "BST3A0"; - } - 1433 - { - title = "Tulip (Cyan)"; - sprite = "BST4A0"; - } - 1434 - { - title = "Tulip (Yellow)"; - sprite = "BST5A0"; - } - 1435 - { - title = "Tulip (Orange)"; - sprite = "BST6A0"; - } - 1440 - { - title = "Cluster (Red)"; - sprite = "BSZ5A0"; - } - 1441 - { - title = "Cluster (Purple)"; - sprite = "BSZ5B0"; - } - 1442 - { - title = "Cluster (Blue)"; - sprite = "BSZ5C0"; - } - 1443 - { - title = "Cluster (Cyan)"; - sprite = "BSZ5D0"; - } - 1444 - { - title = "Cluster (Yellow)"; - sprite = "BSZ5E0"; - } - 1445 - { - title = "Cluster (Orange)"; - sprite = "BSZ5F0"; - } - 1450 - { - title = "Bush (Red)"; - sprite = "BSZ6A0"; - } - 1451 - { - title = "Bush (Purple)"; - sprite = "BSZ6B0"; - } - 1452 - { - title = "Bush (Blue)"; - sprite = "BSZ6C0"; - } - 1453 - { - title = "Bush (Cyan)"; - sprite = "BSZ6D0"; - } - 1454 - { - title = "Bush (Yellow)"; - sprite = "BSZ6E0"; - } - 1455 - { - title = "Bush (Orange)"; - sprite = "BSZ6F0"; - } - 1460 - { - title = "Vine (Red)"; - sprite = "BSZ7A0"; - } - 1461 - { - title = "Vine (Purple)"; - sprite = "BSZ7B0"; - } - 1462 - { - title = "Vine (Blue)"; - sprite = "BSZ7C0"; - } - 1463 - { - title = "Vine (Cyan)"; - sprite = "BSZ7D0"; - } - 1464 - { - title = "Vine (Yellow)"; - sprite = "BSZ7E0"; - } - 1465 - { - title = "Vine (Orange)"; - sprite = "BSZ7F0"; - } - 1470 - { - title = "BSZ Shrub"; - sprite = "BSZ8A0"; - } - 1471 - { - title = "BSZ Clover"; - sprite = "BSZ8B0"; - } - 1473 - { - title = "Palm Tree (Big)"; - width = 16; - height = 160; - sprite = "BSZ8D0"; - } - 1475 - { - title = "Palm Tree (Small)"; - width = 16; - height = 80; - sprite = "BSZ8F0"; - } - } - - azuretemple - { - color = 10; // Green - title = "Azure Temple"; - - 1500 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle"; - sprite = "BGARA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1501 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Up)"; - sprite = "BGARA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1502 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Down)"; - sprite = "BGARA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1503 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Long)"; - sprite = "BGARA1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1504 - { - title = "ATZ Target"; - sprite = "RCRYB0"; - width = 24; - height = 32; - } - 1505 - { - title = "Green Flame"; - sprite = "CFLMA0E0"; - width = 8; - height = 32; - } - 1506 - { - arrow = 1; - blocking = 2; - title = "Blue Gargoyle"; - sprite = "BGARD1"; - width = 16; - height = 40; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - } - - dreamhill - { - color = 10; // Green - title = "Dream Hill"; - - 1600 - { - title = "Spring Tree"; - sprite = "TRE6A0"; - width = 16; - height = 32; - } - 1601 - { - title = "Shleep"; - sprite = "SHLPA0"; - width = 24; - height = 32; - } - 1602 - { - title = "Pian"; - sprite = "NTPNALAR"; - width = 16; - height = 32; - } - } - - nightstrk - { - color = 13; // Pink - title = "NiGHTS Track"; - width = 8; - height = 4096; - sprite = "UNKNA0"; - - 1700 - { - title = "Axis"; - sprite = "internal:axis1"; - circle = 1; - unflippable = true; - ignoreZ = true; - flagsvaluetext = "Order"; - angletext = "Radius/Direction"; - parametertext = "Mare"; - } - 1701 - { - title = "Axis Transfer"; - sprite = "internal:axis2"; - unflippable = true; - ignoreZ = true; - flagsvaluetext = "Order"; - parametertext = "Mare"; - } - 1702 - { - title = "Axis Transfer Line"; - sprite = "internal:axis3"; - unflippable = true; - ignoreZ = true; - flagsvaluetext = "Order"; - parametertext = "Mare"; - } - 1710 - { - title = "Ideya Capture"; - sprite = "CAPSA0"; - width = 72; - height = 144; - angletext = "Rings"; - parametertext = "Mare"; - } - } - - nights - { - color = 13; // Pink - title = "NiGHTS Items"; - width = 16; - height = 32; - - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - flags1text = "[1] Align player to middle"; - flags4text = "[4] Align player to top"; - flags8text = "[8] Die upon time up"; - angletext = "Time limit"; - parametertext = "Height"; - } - 1704 - { - arrow = 1; - title = "NiGHTS Bumper"; - sprite = "NBMPG3G7"; - width = 32; - height = 64; - unflippable = true; - flagsvaluetext = "Pitch"; - angletext = "Yaw"; - } - 1705 - { - arrow = 1; - title = "Hoop (Generic)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - unflippable = true; - centerHitbox = true; - flagsvaluetext = "Height"; - angletext = "Pitch/Yaw"; - } - 1706 - { - title = "Blue Sphere"; - sprite = "SPHRA0"; - width = 16; - height = 24; - flags8height = 24; - flags8text = "[8] Float"; - unflippable = true; - } - 1707 - { - title = "Super Paraloop"; - sprite = "NPRUA0"; - flags4text = "[4] Bonus time only"; - flags8text = "[8] Spawn immediately"; - } - 1708 - { - title = "Drill Refill"; - sprite = "NPRUB0"; - flags4text = "[4] Bonus time only"; - flags8text = "[8] Spawn immediately"; - } - 1709 - { - title = "Nightopian Helper"; - sprite = "NPRUC0"; - flags4text = "[4] Bonus time only"; - flags8text = "[8] Spawn immediately"; - } - 1711 - { - title = "Extra Time"; - sprite = "NPRUD0"; - flags4text = "[4] Bonus time only"; - flags8text = "[8] Spawn immediately"; - } - 1712 - { - title = "Link Freeze"; - sprite = "NPRUE0"; - flags4text = "[4] Bonus time only"; - flags8text = "[8] Spawn immediately"; - } - 1713 - { - arrow = 1; - title = "Hoop (Customizable)"; - flags1text = "[1] Radius +16"; - flags2text = "[2] Radius +32"; - flags4text = "[4] Radius +64"; - flags8text = "[8] Radius +128"; - sprite = "HOOPA0"; - width = 80; - height = 160; - unflippable = true; - centerHitbox = true; - } - 1714 - { - title = "Ideya Anchor Point"; - sprite = "internal:axis1"; - width = 8; - height = 16; - parametertext = "Ideya"; - } - } - - mario - { - color = 6; // Brown - title = "Mario"; - - 1800 - { - title = "Coin"; - sprite = "COINA0"; - width = 16; - height = 24; - flags8height = 24; - flags8text = "[8] Float"; - } - 1801 - { - arrow = 1; - title = "Goomba"; - sprite = "GOOMA0"; - width = 24; - height = 32; - } - 1802 - { - arrow = 1; - title = "Goomba (Blue)"; - sprite = "BGOMA0"; - width = 24; - height = 32; - } - 1803 - { - title = "Fire Flower"; - sprite = "FFWRB0"; - width = 16; - height = 32; - } - 1804 - { - title = "Koopa Shell"; - sprite = "SHLLA1"; - width = 16; - height = 20; - } - 1805 - { - title = "Puma (Jumping Fireball)"; - sprite = "PUMAA0"; - width = 8; - height = 16; - angletext = "Jump strength"; - } - 1806 - { - title = "King Bowser"; - sprite = "KOOPA0"; - width = 16; - height = 48; - } - 1807 - { - title = "Axe"; - sprite = "MAXEA0"; - width = 8; - height = 16; - } - 1808 - { - title = "Bush (Short)"; - sprite = "MUS1A0"; - width = 16; - height = 32; - } - 1809 - { - title = "Bush (Tall)"; - sprite = "MUS2A0"; - width = 16; - height = 32; - } - 1810 - { - title = "Toad"; - sprite = "TOADA0"; - width = 8; - height = 32; - } - } - - christmasdisco - { - color = 10; // Green - title = "Christmas & Disco"; - - 1850 - { - title = "Christmas Pole"; - sprite = "XMS1A0"; - width = 16; - height = 40; - } - 1851 - { - title = "Candy Cane"; - sprite = "XMS2A0"; - width = 8; - height = 32; - } - 1852 - { - blocking = 2; - title = "Snowman"; - sprite = "XMS3A0"; - width = 16; - height = 64; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1853 - { - blocking = 2; - title = "Snowman (With Hat)"; - sprite = "XMS3B0"; - width = 16; - height = 80; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - 1854 - { - title = "Lamp Post"; - sprite = "XMS4A0"; - width = 8; - height = 120; - } - 1855 - { - title = "Lamp Post (Snow)"; - sprite = "XMS4B0"; - width = 8; - height = 120; - } - 1856 - { - title = "Hanging Star"; - sprite = "XMS5A0"; - width = 4; - height = 80; - hangs = 1; - } - 1857 - { - title = "Berry Bush (Snow)"; - sprite = "BUS1B0"; - width = 16; - height = 32; - } - 1858 - { - title = "Bush (Snow)"; - sprite = "BUS2B0"; - width = 16; - height = 32; - } - 1859 - { - title = "Blueberry Bush (Snow)"; - sprite = "BUS3B0"; - width = 16; - height = 32; - } - 1875 - { - title = "Disco Ball"; - sprite = "DBALA0"; - width = 16; - height = 54; - hangs = 1; - } - 1876 - { - arrow = 1; - blocking = 2; - title = "Eggman Disco Statue"; - sprite = "ESTAB1"; - width = 20; - height = 96; - flags4text = "[4] Slides when pushed"; - flags8text = "[8] Not pushable"; - } - } - - stalagmites - { - color = 10; // Green - title = "Stalagmites"; - width = 16; - height = 40; - - 1900 - { - title = "Brown Stalagmite (Tall)"; - sprite = "STLGA0"; - width = 16; - height = 40; - } - 1901 - { - title = "Brown Stalagmite"; - sprite = "STLGB0"; - width = 16; - height = 40; - } - 1902 - { - title = "Orange Stalagmite (Tall)"; - sprite = "STLGC0"; - width = 16; - height = 40; - } - 1903 - { - title = "Orange Stalagmite"; - sprite = "STLGD0"; - width = 16; - height = 40; - } - 1904 - { - title = "Red Stalagmite (Tall)"; - sprite = "STLGE0"; - width = 16; - height = 40; - } - 1905 - { - title = "Red Stalagmite"; - sprite = "STLGF0"; - width = 16; - height = 40; - } - 1906 - { - title = "Gray Stalagmite (Tall)"; - sprite = "STLGG0"; - width = 24; - height = 96; - } - 1907 - { - title = "Gray Stalagmite"; - sprite = "STLGH0"; - width = 16; - height = 40; - } - 1908 - { - title = "Blue Stalagmite (Tall)"; - sprite = "STLGI0"; - width = 16; - height = 40; - } - 1909 - { - title = "Blue Stalagmite"; - sprite = "STLGJ0"; - width = 16; - height = 40; - } - } - - hauntedheights - { - color = 10; // Green - title = "Haunted Heights"; - - 2000 - { - title = "Smashing Spikeball"; - sprite = "FMCEA0"; - width = 18; - height = 28; - angletext = "Initial delay"; - } - 2001 - { - title = "HHZ Grass"; - sprite = "HHZMA0"; - width = 16; - height = 40; - } - 2002 - { - title = "HHZ Tentacle 1"; - sprite = "HHZMB0"; - width = 16; - height = 40; - } - 2003 - { - title = "HHZ Tentacle 2"; - sprite = "HHZMC0"; - width = 16; - height = 40; - } - 2004 - { - title = "HHZ Stalagmite (Tall)"; - sprite = "HHZME0"; - width = 16; - height = 40; - } - 2005 - { - title = "HHZ Stalagmite (Short)"; - sprite = "HHZMF0"; - width = 16; - height = 40; - } - 2006 - { - title = "Jack-o'-lantern 1"; - sprite = "PUMKA0"; - width = 16; - height = 40; - flags1text = "Don't flicker"; - } - 2007 - { - title = "Jack-o'-lantern 2"; - sprite = "PUMKB0"; - width = 16; - height = 40; - flags1text = "Don't flicker"; - } - 2008 - { - title = "Jack-o'-lantern 3"; - sprite = "PUMKC0"; - width = 16; - height = 40; - flags1text = "Don't flicker"; - } - 2009 - { - title = "Purple Mushroom"; - sprite = "SHRMD0"; - width = 16; - height = 48; - } - 2010 - { - title = "HHZ Tree"; - sprite = "HHPLC0"; - width = 12; - height = 40; - } - } - - frozenhillside - { - color = 10; // Green - title = "Frozen Hillside"; - - 2100 - { - title = "Ice Shard (Small)"; - sprite = "FHZIA0"; - width = 8; - height = 32; - } - 2101 - { - title = "Ice Shard (Large)"; - sprite = "FHZIB0"; - width = 8; - height = 32; - } - 2102 - { - title = "Crystal Tree (Aqua)"; - sprite = "TRE3A0"; - width = 20; - height = 200; - } - 2103 - { - title = "Crystal Tree (Pink)"; - sprite = "TRE3B0"; - width = 20; - height = 200; - } - 2104 - { - title = "Amy Cameo"; - sprite = "ROSYA1"; - width = 16; - height = 48; - flags1text = "[1] Grayscale mode"; - } - 2105 - { - title = "Mistletoe"; - sprite = "XMS6A0"; - width = 52; - height = 106; - } - } - - flickies - { - color = 10; // Green - title = "Flickies"; - width = 8; - height = 20; - flags1text = "[1] Move aimlessly"; - flags4text = "[4] No movement"; - flags8text = "[8] Hop"; - angletext = "Radius"; - - 2200 - { - title = "Bluebird"; - sprite = "FL01A1"; - } - 2201 - { - title = "Rabbit"; - sprite = "FL02A1"; - } - 2202 - { - title = "Chicken"; - sprite = "FL03A1"; - } - 2203 - { - title = "Seal"; - sprite = "FL04A1"; - } - 2204 - { - title = "Pig"; - sprite = "FL05A1"; - } - 2205 - { - title = "Chipmunk"; - sprite = "FL06A1"; - } - 2206 - { - title = "Penguin"; - sprite = "FL07A1"; - } - 2207 - { - title = "Fish"; - sprite = "FL08A1"; - parametertext = "Color"; - } - 2208 - { - title = "Ram"; - sprite = "FL09A1"; - } - 2209 - { - title = "Puffin"; - sprite = "FL10A1"; - } - 2210 - { - title = "Cow"; - sprite = "FL11A1"; - } - 2211 - { - title = "Rat"; - sprite = "FL12A1"; - } - 2212 - { - title = "Bear"; - sprite = "FL13A1"; - } - 2213 - { - title = "Dove"; - sprite = "FL14A1"; - } - 2214 - { - title = "Cat"; - sprite = "FL15A1"; - } - 2215 - { - title = "Canary"; - sprite = "FL16A1"; - } - 2216 - { - title = "Spider"; - sprite = "FS01A1"; - } - 2217 - { - title = "Bat"; - sprite = "FS02A0"; - } - } -} - -//Default things filters -thingsfilters -{ - - filter0 - { - name = "Player starts"; - category = "starts"; - type = -1; - } - - - filter1 - { - name = "Enemies"; - category = "enemies"; - type = -1; - - } - - - filter2 - { - name = "NiGHTS Track"; - category = "nightstrk"; - type = -1; - - } - - - filter3 - { - name = "Normal Gravity"; - category = ""; - type = -1; - - fields - { - 2 = false; - } - - } - - - filter4 - { - name = "Reverse Gravity"; - category = ""; - type = -1; - - fields - { - 2 = true; - } - - } -} diff --git a/extras/conf/SRB2_22Doom.cfg b/extras/conf/SRB2_22Doom.cfg new file mode 100644 index 000000000..65e49d387 --- /dev/null +++ b/extras/conf/SRB2_22Doom.cfg @@ -0,0 +1,38 @@ +/************************************************************************\ + Zone Builder Game Configuration for Sonic Robo Blast 2 Version 2.2 +\************************************************************************/ + +// This is required to prevent accidental use of a different configuration +type = "Doom Builder 2 Game Configuration"; + +// This is the title to show for this game +game = "Sonic Robo Blast 2 - 2.2 (Doom format)"; + +// This is the simplified game engine/sourceport name +engine = "zdoom"; + +// Settings common to all games and all map formats +include("Includes\\SRB222_common.cfg", "common"); + +// Settings common to Doom map format +include("Includes\\SRB222_common.cfg", "mapformat_doom"); + +include("Includes\\Game_SRB222.cfg"); + +// Script lumps detection +scriptlumpnames +{ + include("Includes\\SRB222_misc.cfg", "scriptlumpnames"); +} + +// THING TYPES +thingtypes +{ + include("Includes\\SRB222_things.cfg"); +} + +//Default things filters +thingsfilters +{ + include("Includes\\SRB222_misc.cfg", "thingsfilters"); +} \ No newline at end of file diff --git a/extras/conf/SRB2_22UDMF.cfg b/extras/conf/SRB2_22UDMF.cfg new file mode 100644 index 000000000..52104ed09 --- /dev/null +++ b/extras/conf/SRB2_22UDMF.cfg @@ -0,0 +1,47 @@ +/************************************************************************\ + Zone Builder Game Configuration for Sonic Robo Blast 2 Version 2.2 +\************************************************************************/ + +// This is required to prevent accidental use of a different configuration +type = "Doom Builder 2 Game Configuration"; + +// This is the title to show for this game +game = "Sonic Robo Blast 2 - 2.2 (UDMF)"; + +// This is the simplified game engine/sourceport name +engine = "zdoom"; + +// Settings common to all games and all map formats +include("Includes\\SRB222_common.cfg", "common"); + +// Settings common to Doom map format +include("Includes\\SRB222_common.cfg", "mapformat_udmf"); + +include("Includes\\Game_SRB222.cfg"); + +// Script lumps detection +scriptlumpnames +{ + include("Includes\\SRB222_misc.cfg", "scriptlumpnames"); +} + +// THING TYPES +thingtypes +{ + include("Includes\\SRB222_things.cfg"); +} + +//Default things filters +thingsfilters +{ + include("Includes\\SRB222_misc.cfg", "thingsfilters"); +} + +// ENUMERATIONS +// Each engine has its own additional thing types +// These are enumerated lists for linedef types and UDMF fields. +enums +{ + // Basic game enums + include("Includes\\SRB222_misc.cfg", "enums"); +} \ No newline at end of file diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 6520a1aa1..4448aaae0 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -611,11 +611,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->health = LONG(players[i].mo->health); rsp->angle = (angle_t)LONG(players[i].mo->angle); -#ifdef ROTSPRITE rsp->rollangle = (angle_t)LONG(players[i].mo->rollangle); -#else - rsp->rollangle = 0; -#endif rsp->x = LONG(players[i].mo->x); rsp->y = LONG(players[i].mo->y); rsp->z = LONG(players[i].mo->z); @@ -766,9 +762,7 @@ static void resynch_read_player(resynch_pak *rsp) //At this point, the player should have a body, whether they were respawned or not. P_UnsetThingPosition(players[i].mo); players[i].mo->angle = (angle_t)LONG(rsp->angle); -#ifdef ROTSPRITE players[i].mo->rollangle = (angle_t)LONG(rsp->rollangle); -#endif players[i].mo->eflags = (UINT16)SHORT(rsp->eflags); players[i].mo->flags = LONG(rsp->flags); players[i].mo->flags2 = LONG(rsp->flags2); @@ -1025,7 +1019,7 @@ static void SV_SendResynch(INT32 node) netbuffer->packettype = PT_RESYNCHEND; netbuffer->u.resynchend.randomseed = P_GetRandSeed(); - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) resynch_write_ctf(&netbuffer->u.resynchend); resynch_write_others(&netbuffer->u.resynchend); @@ -2111,10 +2105,10 @@ static void CL_ConnectToServer(boolean viams) if (i != -1) { - UINT8 num = serverlist[i].info.gametype; + UINT16 num = serverlist[i].info.gametype; const char *gametypestr = NULL; CONS_Printf(M_GetText("Connecting to: %s\n"), serverlist[i].info.servername); - if (num < NUMGAMETYPES) + if (num < gametypecount) gametypestr = Gametype_Names[num]; if (gametypestr) CONS_Printf(M_GetText("Gametype: %s\n"), gametypestr); @@ -2430,7 +2424,7 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) } } - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! // If in a special stage, redistribute the player's spheres across @@ -2486,6 +2480,17 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) (void)reason; #endif + // don't look through someone's view who isn't there + if (playernum == displayplayer) + { +#ifdef HAVE_BLUA + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer], true); +#endif + displayplayer = consoleplayer; + } + // Reset player data CL_ClearPlayer(playernum); @@ -2503,16 +2508,13 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason) RemoveAdminPlayer(playernum); // don't stay admin after you're gone } - if (playernum == displayplayer) - displayplayer = consoleplayer; // don't look through someone's view who isn't there - #ifdef HAVE_BLUA LUA_InvalidatePlayer(&players[playernum]); #endif if (G_TagGametype()) //Check if you still have a game. Location flexible. =P P_CheckSurvivors(); - else if (gametype == GT_RACE || gametype == GT_COMPETITION) + else if (gametyperules & GTR_RACE) P_CheckRacers(); } @@ -3461,7 +3463,7 @@ void SV_StartSinglePlayerServer(void) server = true; netgame = false; multiplayer = false; - gametype = GT_COOP; + G_SetGametype(GT_COOP); // no more tic the game with this settings! SV_StopServer(); @@ -3740,7 +3742,7 @@ static void HandlePacketFromAwayNode(SINT8 node) if (client) { maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); - gametype = netbuffer->u.servercfg.gametype; + G_SetGametype(netbuffer->u.servercfg.gametype); modifiedgame = netbuffer->u.servercfg.modifiedgame; for (j = 0; j < MAXPLAYERS; j++) adminplayers[j] = netbuffer->u.servercfg.adminplayers[j]; @@ -4124,7 +4126,7 @@ static void HandlePacketFromPlayer(SINT8 node) P_SetRandSeed(netbuffer->u.resynchend.randomseed); - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) resynch_read_ctf(&netbuffer->u.resynchend); resynch_read_others(&netbuffer->u.resynchend); diff --git a/src/d_main.c b/src/d_main.c index c4b0d7117..e25ef998e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -762,7 +762,7 @@ void D_StartTitle(void) gameaction = ga_nothing; displayplayer = consoleplayer = 0; - gametype = GT_COOP; + G_SetGametype(GT_COOP); paused = false; advancedemo = false; F_InitMenuPresValues(); @@ -1419,14 +1419,14 @@ void D_SRB2Main(void) if (newgametype == -1) // reached end of the list with no match { j = atoi(sgametype); // assume they gave us a gametype number, which is okay too - if (j >= 0 && j < NUMGAMETYPES) + if (j >= 0 && j < gametypecount) newgametype = (INT16)j; } if (newgametype != -1) { j = gametype; - gametype = newgametype; + G_SetGametype(newgametype); D_GameTypeChanged(j); } } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 262d0d1bc..4e14ca25f 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -327,6 +327,10 @@ consvar_t cv_numlaps = {"numlaps", "4", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_con static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {50, "MAX"}, {0, "Map default"}, {0, NULL}}; consvar_t cv_basenumlaps = {"basenumlaps", "Map default", CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange, 0, NULL, NULL, 0, 0, NULL}; +// Point and time limits for every gametype +INT32 pointlimits[NUMGAMETYPES]; +INT32 timelimits[NUMGAMETYPES]; + // log elemental hazards -- not a netvar, is local to current player consvar_t cv_hazardlog = {"hazardlog", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -381,6 +385,9 @@ char timedemo_csv_id[256]; boolean timedemo_quit; INT16 gametype = GT_COOP; +UINT32 gametyperules = 0; +INT16 gametypecount = (GT_CTF + 1); + boolean splitscreen = false; boolean circuitmap = false; INT32 adminplayers[MAXPLAYERS]; @@ -1126,7 +1133,7 @@ UINT8 CanChangeSkin(INT32 playernum) return true; // Can change skin during initial countdown. - if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE) + if ((gametyperules & GTR_RACE) && leveltime < 4*TICRATE) return true; if (G_TagGametype()) @@ -1942,7 +1949,7 @@ static void Command_Map_f(void) if (isdigit(gametypename[0])) { d = atoi(gametypename); - if (d >= 0 && d < NUMGAMETYPES) + if (d >= 0 && d < gametypecount) newgametype = d; else { @@ -1950,7 +1957,7 @@ static void Command_Map_f(void) "Gametype number %d is out of range. Use a number between" " 0 and %d inclusive. ...Or just use the name. :v\n", d, - NUMGAMETYPES-1); + gametypecount-1); Z_Free(realmapname); Z_Free(mapname); return; @@ -2069,8 +2076,9 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum) lastgametype = gametype; gametype = READUINT8(*cp); + G_SetGametype(gametype); // I fear putting that macro as an argument - if (gametype < 0 || gametype >= NUMGAMETYPES) + if (gametype < 0 || gametype >= gametypecount) gametype = lastgametype; else if (gametype != lastgametype) D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype @@ -2413,7 +2421,7 @@ static void Command_Teamchange_f(void) } //additional check for hide and seek. Don't allow change of status after hidetime ends. - if (gametype == GT_HIDEANDSEEK && leveltime >= (hidetime * TICRATE)) + if ((gametyperules & GTR_HIDEFROZEN) && leveltime >= (hidetime * TICRATE)) { CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); return; @@ -2510,7 +2518,7 @@ static void Command_Teamchange2_f(void) } //additional check for hide and seek. Don't allow change of status after hidetime ends. - if (gametype == GT_HIDEANDSEEK && leveltime >= (hidetime * TICRATE)) + if ((gametyperules & GTR_HIDEFROZEN) && leveltime >= (hidetime * TICRATE)) { CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); return; @@ -2639,7 +2647,7 @@ static void Command_ServerTeamChange_f(void) } //additional check for hide and seek. Don't allow change of status after hidetime ends. - if (gametype == GT_HIDEANDSEEK && leveltime >= (hidetime * TICRATE)) + if ((gametyperules & GTR_HIDEFROZEN) && leveltime >= (hidetime * TICRATE)) { CONS_Alert(CONS_NOTICE, M_GetText("Hiding time expired; no Hide and Seek status changes allowed!\n")); return; @@ -2728,6 +2736,16 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) return; } +#ifdef HAVE_BLUA + // Don't switch team, just go away, please, go awaayyyy, aaauuauugghhhghgh + if (!LUAh_TeamSwitch(&players[playernum], NetPacket.packet.newteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled)) + return; +#endif + + //no status changes after hidetime + if ((gametyperules & GTR_HIDEFROZEN) && (leveltime >= (hidetime * TICRATE))) + error = true; + //Make sure that the right team number is sent. Keep in mind that normal clients cannot change to certain teams in certain gametypes. switch (gametype) { @@ -2882,7 +2900,15 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) //reset view if you are changed, or viewing someone who was changed. if (playernum == consoleplayer || displayplayer == playernum) + { +#ifdef HAVE_BLUA + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + if (displayplayer != consoleplayer) // You're already viewing yourself. No big deal. + LUAh_ViewpointSwitch(&players[playernum], &players[displayplayer], true); +#endif displayplayer = consoleplayer; + } if (G_GametypeHasTeams()) { @@ -3618,7 +3644,7 @@ static void Command_ShowGametype_f(void) } // get name string for current gametype - if (gametype >= 0 && gametype < NUMGAMETYPES) + if (gametype >= 0 && gametype < gametypecount) gametypestr = Gametype_Names[gametype]; if (gametypestr) @@ -3680,7 +3706,7 @@ void ItemFinder_OnChange(void) static void PointLimit_OnChange(void) { // Don't allow pointlimit in Single Player/Co-Op/Race! - if (server && Playing() && G_PlatformGametype()) + if (server && Playing() && !(gametyperules & GTR_POINTLIMIT)) { if (cv_pointlimit.value) CV_StealthSetValue(&cv_pointlimit, 0); @@ -3843,7 +3869,7 @@ UINT32 timelimitintics = 0; static void TimeLimit_OnChange(void) { // Don't allow timelimit in Single Player/Co-Op/Race! - if (server && Playing() && cv_timelimit.value != 0 && G_PlatformGametype()) + if (server && Playing() && cv_timelimit.value != 0 && !(gametyperules & GTR_TIMELIMIT)) { CV_SetValue(&cv_timelimit, 0); return; @@ -3879,9 +3905,9 @@ void D_GameTypeChanged(INT32 lastgametype) { const char *oldgt = NULL, *newgt = NULL; - if (lastgametype >= 0 && lastgametype < NUMGAMETYPES) + if (lastgametype >= 0 && lastgametype < gametypecount) oldgt = Gametype_Names[lastgametype]; - if (gametype >= 0 && lastgametype < NUMGAMETYPES) + if (gametype >= 0 && lastgametype < gametypecount) newgt = Gametype_Names[gametype]; if (oldgt && newgt) @@ -3935,11 +3961,20 @@ void D_GameTypeChanged(INT32 lastgametype) if (!cv_itemrespawntime.changed) CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally break; + default: + if (!cv_timelimit.changed && !cv_pointlimit.changed) // user hasn't changed limits + { + CV_SetValue(&cv_timelimit, timelimits[gametype]); + CV_SetValue(&cv_pointlimit, pointlimits[gametype]); + } + if (!cv_itemrespawntime.changed) + CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally + break; } } else if (!multiplayer && !netgame) { - gametype = GT_COOP; + G_SetGametype(GT_COOP); // These shouldn't matter anymore //CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); //CV_SetValue(&cv_itemrespawn, 0); @@ -3948,7 +3983,7 @@ void D_GameTypeChanged(INT32 lastgametype) // reset timelimit and pointlimit in race/coop, prevent stupid cheats if (server) { - if (G_PlatformGametype()) + if (!(gametyperules & GTR_POINTLIMIT)) { if (cv_timelimit.value) CV_SetValue(&cv_timelimit, 0); @@ -3966,6 +4001,7 @@ void D_GameTypeChanged(INT32 lastgametype) // When swapping to a gametype that supports spectators, // make everyone a spectator initially. + // Averted with GTR_NOSPECTATORSPAWN. if (!splitscreen && (G_GametypeHasSpectators())) { INT32 i; @@ -3973,7 +4009,7 @@ void D_GameTypeChanged(INT32 lastgametype) if (playeringame[i]) { players[i].ctfteam = 0; - players[i].spectator = true; + players[i].spectator = (gametyperules & GTR_NOSPECTATORSPAWN) ? false : true; } } diff --git a/src/dehacked.c b/src/dehacked.c index 0d1881c25..b77939c2a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -22,6 +22,7 @@ #include "m_menu.h" #include "m_misc.h" #include "f_finale.h" +#include "y_inter.h" #include "dehacked.h" #include "st_stuff.h" #include "i_system.h" @@ -76,6 +77,7 @@ static UINT16 get_mus(const char *word, UINT8 dehacked_mode); static hudnum_t get_huditem(const char *word); static menutype_t get_menutype(const char *word); #ifndef HAVE_BLUA +static INT16 get_gametype(const char *word); static powertype_t get_power(const char *word); #endif @@ -590,6 +592,16 @@ static void readfreeslots(MYFILE *f) } else CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n"); } + else if (fastcmp(type, "TOL")) + { + if (lastcustomtol > 31) + CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n"); + else + { + G_AddTOL((1<pivot[frame].x = value; else if (fastcmp(word, "YPIVOT")) sprinfo->pivot[frame].y = value; else if (fastcmp(word, "ROTAXIS")) sprinfo->pivot[frame].rotaxis = value; -#endif else { f->curpos = lastline; @@ -1095,10 +1105,10 @@ static void readsprite2(MYFILE *f, INT32 num) Z_Free(s); } -static const struct { - const char *name; - const UINT16 flag; -} TYPEOFLEVEL[] = { +INT32 numtolinfo = NUMBASETOL; +UINT32 lastcustomtol = 13; + +tolinfo_t TYPEOFLEVEL[NUMMAXTOL] = { {"SOLO",TOL_SP}, {"SP",TOL_SP}, {"SINGLEPLAYER",TOL_SP}, @@ -1114,8 +1124,6 @@ static const struct { {"TAG",TOL_TAG}, {"CTF",TOL_CTF}, - {"CUSTOM",TOL_CUSTOM}, - {"2D",TOL_2D}, {"MARIO",TOL_MARIO}, {"NIGHTS",TOL_NIGHTS}, @@ -1128,6 +1136,216 @@ static const struct { {NULL, 0} }; +// copypasted from readPlayer :sleep: +static const char *const GAMETYPERULE_LIST[]; +static void readgametype(MYFILE *f, char *gtname) +{ + char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + char *word; + char *word2, *word2lwr = NULL; + char *tmp; + INT32 i, j; + + INT16 newgtidx = 0; + UINT32 newgtrules = 0; + UINT32 newgttol = 0; + INT32 newgtpointlimit = 0; + INT32 newgttimelimit = 0; + UINT8 newgtleftcolor = 0; + UINT8 newgtrightcolor = 0; + INT16 newgtrankingstype = -1; + int newgtinttype = 0; + char gtdescription[441]; + char gtconst[MAXLINELEN]; + + // Empty strings. + gtdescription[0] = '\0'; + gtconst[0] = '\0'; + + do + { + if (myfgets(s, MAXLINELEN, f)) + { + if (s[0] == '\n') + break; + + word = strtok(s, " "); + if (word) + strupr(word); + else + break; + + if (fastcmp(word, "DESCRIPTION")) + { + char *descr = NULL; + + for (i = 0; i < MAXLINELEN-3; i++) + { + if (s[i] == '=') + { + descr = &s[i+2]; + break; + } + } + if (descr) + { + strcpy(gtdescription, descr); + strcat(gtdescription, myhashfgets(descr, sizeof (gtdescription), f)); + } + else + strcpy(gtdescription, ""); + + // For some reason, cutting the string did not work above. Most likely due to strcpy or strcat... + // It works down here, though. + { + INT32 numline = 0; + for (i = 0; i < MAXLINELEN-1; i++) + { + if (numline < 20 && gtdescription[i] == '\n') + numline++; + + if (numline >= 20 || gtdescription[i] == '\0' || gtdescription[i] == '#') + break; + } + } + gtdescription[strlen(gtdescription)-1] = '\0'; + gtdescription[i] = '\0'; + continue; + } + + word2 = strtok(NULL, " = "); + if (word2) + { + if (!word2lwr) + word2lwr = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + strcpy(word2lwr, word2); + strupr(word2); + } + else + break; + + if (word2[strlen(word2)-1] == '\n') + word2[strlen(word2)-1] = '\0'; + i = atoi(word2); + + // Game type rules + if (fastcmp(word, "RULES")) + { + // GTR_ + newgtrules = (UINT32)get_number(word2); + } + // Identifier + else if (fastcmp(word, "IDENTIFIER")) + { + // GT_ + strncpy(gtconst, word2, MAXLINELEN); + } + // Point and time limits + else if (fastcmp(word, "DEFAULTPOINTLIMIT")) + newgtpointlimit = (INT32)i; + else if (fastcmp(word, "DEFAULTTIMELIMIT")) + newgttimelimit = (INT32)i; + // Level platter + else if (fastcmp(word, "HEADERCOLOR") || fastcmp(word, "HEADERCOLOUR")) + newgtleftcolor = newgtrightcolor = (UINT8)get_number(word2); + else if (fastcmp(word, "HEADERLEFTCOLOR") || fastcmp(word, "HEADERLEFTCOLOUR")) + newgtleftcolor = (UINT8)get_number(word2); + else if (fastcmp(word, "HEADERRIGHTCOLOR") || fastcmp(word, "HEADERRIGHTCOLOUR")) + newgtrightcolor = (UINT8)get_number(word2); + // Rankings type + else if (fastcmp(word, "RANKINGTYPE")) + { + // Case insensitive + newgtrankingstype = (int)get_number(word2); + } + // Intermission type + else if (fastcmp(word, "INTERMISSIONTYPE")) + { + // Case sensitive + newgtinttype = (int)get_number(word2lwr); + } + // Type of level + else if (fastcmp(word, "TYPEOFLEVEL")) + { + if (i) // it's just a number + newgttol = (UINT32)i; + else + { + UINT16 tol = 0; + tmp = strtok(word2,","); + do { + for (i = 0; TYPEOFLEVEL[i].name; i++) + if (fasticmp(tmp, TYPEOFLEVEL[i].name)) + break; + if (!TYPEOFLEVEL[i].name) + deh_warning("readgametype %s: unknown typeoflevel flag %s\n", gtname, tmp); + tol |= TYPEOFLEVEL[i].flag; + } while((tmp = strtok(NULL,",")) != NULL); + newgttol = tol; + } + } + // The SOC probably provided gametype rules as words, + // instead of using the RULES keyword. + // Like for example "NOSPECTATORSPAWN = TRUE". + // This is completely valid, and looks better anyway. + else + { + UINT32 wordgt = 0; + for (j = 0; GAMETYPERULE_LIST[j]; j++) + if (fastcmp(word, GAMETYPERULE_LIST[j])) { + if (!j) // GTR_CAMPAIGN + wordgt |= 1; + else + wordgt |= (1<typeoflevel = (UINT16)i; + mapheaderinfo[num-1]->typeoflevel = (UINT32)i; else { UINT16 tol = 0; @@ -2690,11 +2908,9 @@ static actionpointer_t actionpointers[] = {{A_SpawnObjectRelative}, "A_SPAWNOBJECTRELATIVE"}, {{A_ChangeAngleRelative}, "A_CHANGEANGLERELATIVE"}, {{A_ChangeAngleAbsolute}, "A_CHANGEANGLEABSOLUTE"}, -#ifdef ROTSPRITE {{A_RollAngle}, "A_ROLLANGLE"}, {{A_ChangeRollAngleRelative},"A_CHANGEROLLANGLERELATIVE"}, {{A_ChangeRollAngleAbsolute},"A_CHANGEROLLANGLEABSOLUTE"}, -#endif {{A_PlaySound}, "A_PLAYSOUND"}, {{A_FindTarget}, "A_FINDTARGET"}, {{A_FindTracer}, "A_FINDTRACER"}, @@ -4172,6 +4388,7 @@ static void ignorelines(MYFILE *f) static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + char textline[MAXLINELEN]; char *word; char *word2; INT32 i; @@ -4192,6 +4409,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) char *traverse; myfgets(s, MAXLINELEN, f); + memcpy(textline, s, MAXLINELEN); if (s[0] == '\n' || s[0] == '#') continue; @@ -4380,6 +4598,36 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) ignorelines(f); } } + else if (fastcmp(word, "GAMETYPE")) + { + // Get the gametype name from textline + // instead of word2, so that gametype names + // aren't allcaps + INT32 c; + for (c = 0; c < MAXLINELEN; c++) + { + if (textline[c] == '\0') + break; + if (textline[c] == ' ') + { + char *gtname = (textline+c+1); + if (gtname) + { + // remove funny characters + INT32 j; + for (j = 0; j < (MAXLINELEN - c); j++) + { + if (gtname[j] == '\0') + break; + if (gtname[j] < 32) + gtname[j] = '\0'; + } + readgametype(f, gtname); + } + break; + } + } + } else if (fastcmp(word, "CUTSCENE")) { if (i > 0 && i < 129) @@ -8650,6 +8898,39 @@ static const char *const PLAYERFLAG_LIST[] = { NULL // stop loop here. }; +static const char *const GAMETYPERULE_LIST[] = { + "CAMPAIGN", + "RINGSLINGER", + "SPECTATORS", + "FRIENDLYFIRE", + "LIVES", + "TEAMS", + "RACE", + "TAG", + "POINTLIMIT", + "TIMELIMIT", + "HIDETIME", + "HIDEFROZEN", + "BLINDFOLDED", + "FIRSTPERSON", + "MATCHEMERALDS", + "TEAMFLAGS", + "PITYSHIELD", + "DEATHPENALTY", + "NOSPECTATORSPAWN", + "DEATHMATCHSTARTS", + "SPECIALSTAGES", + "EMERALDTOKENS", + "EMERALDHUNT", + "SPAWNENEMIES", + "ALLOWEXIT", + "NOTITLECARD", + "OVERTIME", + "HURTMESSAGES", + "SPAWNINVUL", + NULL +}; + #ifdef HAVE_BLUA // Linedef flags static const char *const ML_LIST[16] = { @@ -9065,21 +9346,6 @@ struct { {"tr_trans90",tr_trans90}, {"NUMTRANSMAPS",NUMTRANSMAPS}, - // Type of levels - {"TOL_SP",TOL_SP}, - {"TOL_COOP",TOL_COOP}, - {"TOL_COMPETITION",TOL_COMPETITION}, - {"TOL_RACE",TOL_RACE}, - {"TOL_MATCH",TOL_MATCH}, - {"TOL_TAG",TOL_TAG}, - {"TOL_CTF",TOL_CTF}, - {"TOL_CUSTOM",TOL_CUSTOM}, - {"TOL_2D",TOL_2D}, - {"TOL_MARIO",TOL_MARIO}, - {"TOL_NIGHTS",TOL_NIGHTS}, - {"TOL_ERZ3",TOL_ERZ3}, - {"TOL_XMAS",TOL_XMAS}, - // Level flags {"LF_SCRIPTISFILE",LF_SCRIPTISFILE}, {"LF_SPEEDMUSIC",LF_SPEEDMUSIC}, @@ -9262,15 +9528,16 @@ struct { {"DMG_CANHURTSELF",DMG_CANHURTSELF}, {"DMG_DEATHMASK",DMG_DEATHMASK}, - // Gametypes, for use with global var "gametype" - {"GT_COOP",GT_COOP}, - {"GT_COMPETITION",GT_COMPETITION}, - {"GT_RACE",GT_RACE}, - {"GT_MATCH",GT_MATCH}, - {"GT_TEAMMATCH",GT_TEAMMATCH}, - {"GT_TAG",GT_TAG}, - {"GT_HIDEANDSEEK",GT_HIDEANDSEEK}, - {"GT_CTF",GT_CTF}, + // Intermission types + {"int_none",int_none}, + {"int_coop",int_coop}, + {"int_match",int_match}, + {"int_teammatch",int_teammatch}, + //{"int_tag",int_tag}, + {"int_ctf",int_ctf}, + {"int_spec",int_spec}, + {"int_race",int_race}, + {"int_comp",int_comp}, // Jingles (jingletype_t) {"JT_NONE",JT_NONE}, @@ -9443,12 +9710,10 @@ struct { {"DI_SOUTHEAST",DI_SOUTHEAST}, {"NUMDIRS",NUMDIRS}, -#ifdef ROTSPRITE // Sprite rotation axis (rotaxis_t) {"ROTAXIS_X",ROTAXIS_X}, {"ROTAXIS_Y",ROTAXIS_Y}, {"ROTAXIS_Z",ROTAXIS_Z}, -#endif // Buttons (ticcmd_t) {"BT_WEAPONMASK",BT_WEAPONMASK}, //our first four bits. @@ -9563,7 +9828,7 @@ struct { }; static mobjtype_t get_mobjtype(const char *word) -{ // Returns the vlaue of MT_ enumerations +{ // Returns the value of MT_ enumerations mobjtype_t i; if (*word >= '0' && *word <= '9') return atoi(word); @@ -9715,8 +9980,22 @@ static menutype_t get_menutype(const char *word) } #ifndef HAVE_BLUA +static INT16 get_gametype(const char *word) +{ // Returns the value of GT_ enumerations + INT16 i; + if (*word >= '0' && *word <= '9') + return atoi(word); + if (fastncmp("GT_",word,3)) + word += 3; // take off the GT_ + for (i = 0; i < NUMGAMETYPES; i++) + if (fastcmp(word, Gametype_ConstantNames[i]+3)) + return i; + deh_warning("Couldn't find gametype named 'GT_%s'",word); + return GT_COOP; +} + static powertype_t get_power(const char *word) -{ // Returns the vlaue of pw_ enumerations +{ // Returns the value of pw_ enumerations powertype_t i; if (*word >= '0' && *word <= '9') return atoi(word); @@ -9910,11 +10189,42 @@ static fixed_t find_const(const char **rword) free(word); return r; } - else if (fastncmp("MN_",word,4)) { + else if (fastncmp("MN_",word,3)) { r = get_menutype(word); free(word); return r; } + else if (fastncmp("GT_",word,4)) { + r = get_gametype(word); + free(word); + return r; + } + else if (fastncmp("GTR_", word, 4)) { + char *p = word+4; + for (i = 0; GAMETYPERULE_LIST[i]; i++) + if (fastcmp(p, GAMETYPERULE_LIST[i])) { + free(word); + return (1< 31) + CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n"); + else + { + UINT32 newtol = (1<playerstate == PST_REBORN || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) + if (paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametyperules & GTR_TAG) && (leveltime < hidetime * TICRATE) && (player->pflags & PF_TAGIT))))) { cmd->angleturn = (INT16)(localangle >> 16); @@ -1159,14 +1159,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) else { if (turnright) - cmd->angleturn = (INT16)(cmd->angleturn - angleturn[tspeed]); + cmd->angleturn = (INT16)(cmd->angleturn - ((angleturn[tspeed] * cv_cam_turnmultiplier.value)>>FRACBITS)); else if (turnleft) - cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]); + cmd->angleturn = (INT16)(cmd->angleturn + ((angleturn[tspeed] * cv_cam_turnmultiplier.value)>>FRACBITS)); if (analogjoystickmove && lookjoystickvector.xaxis != 0) { // JOYAXISRANGE should be 1023 (divide by 1024) - cmd->angleturn = (INT16)(cmd->angleturn - ((lookjoystickvector.xaxis * angleturn[1]) >> 10)); // ANALOG! + cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 10) * cv_cam_turnmultiplier.value)>>FRACBITS)); // ANALOG! } } @@ -1379,7 +1379,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) //Reset away view if a command is given. if ((cmd->forwardmove || cmd->sidemove || cmd->buttons) && displayplayer != consoleplayer) + { +#ifdef HAVE_BLUA + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUAh_ViewpointSwitch(player, &players[displayplayer], true); +#endif displayplayer = consoleplayer; + } } // like the g_buildticcmd 1 but using mouse2, gamcontrolbis, ... @@ -1497,14 +1504,14 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) else { if (turnright) - cmd->angleturn = (INT16)(cmd->angleturn - angleturn[tspeed]); + cmd->angleturn = (INT16)(cmd->angleturn - (((angleturn[tspeed]<>FRACBITS)); else if (turnleft) - cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]); + cmd->angleturn = (INT16)(cmd->angleturn + (((angleturn[tspeed]<>FRACBITS)); if (analogjoystickmove && lookjoystickvector.xaxis != 0) { // JOYAXISRANGE should be 1023 (divide by 1024) - cmd->angleturn = (INT16)(cmd->angleturn - ((lookjoystickvector.xaxis * angleturn[1]) >> 10)); // ANALOG! + cmd->angleturn = (INT16)(cmd->angleturn - ((((lookjoystickvector.xaxis * angleturn[1]) >> 10) * cv_cam2_turnmultiplier.value)>>FRACBITS)); // ANALOG! } } @@ -1885,7 +1892,7 @@ void G_StartTitleCard(void) { // The title card has been disabled for this map. // Oh well. - if (mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD) + if (!G_IsTitleCardAvailable()) { WipeStageTitle = false; return; @@ -1930,6 +1937,23 @@ void G_PreLevelTitleCard(void) wipestyleflags = WSF_CROSSFADE; } +// +// Returns true if the current level has a title card. +// +boolean G_IsTitleCardAvailable(void) +{ + // The current level header explicitly disabled the title card. + if (mapheaderinfo[gamemap-1]->levelflags & LF_NOTITLECARD) + return false; + + // The current gametype doesn't have a title card. + if (gametyperules & GTR_NOTITLECARD) + return false; + + // The title card is available. + return true; +} + INT32 pausedelay = 0; boolean pausebreakkey = false; static INT32 camtoggledelay, camtoggledelay2 = 0; @@ -2020,6 +2044,11 @@ boolean G_Responder(event_t *ev) if (gamestate == GS_LEVEL && ev->type == ev_keydown && (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1])) { + // ViewpointSwitch Lua hook. +#ifdef HAVE_BLUA + UINT8 canSwitchView = 0; +#endif + if (splitscreen || !netgame) displayplayer = consoleplayer; else @@ -2034,6 +2063,15 @@ boolean G_Responder(event_t *ev) if (!playeringame[displayplayer]) continue; +#ifdef HAVE_BLUA + // Call ViewpointSwitch hooks here. + canSwitchView = LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer], false); + if (canSwitchView == 1) // Set viewpoint to this player + break; + else if (canSwitchView == 2) // Skip this player + continue; +#endif + if (players[displayplayer].spectator) continue; @@ -2642,7 +2680,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) // -- CTF -- // Order: CTF->DM->Coop - if (gametype == GT_CTF && players[playernum].ctfteam) + if ((gametyperules & (GTR_TEAMFLAGS|GTR_TEAMS)) && players[playernum].ctfteam) { if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start @@ -2651,7 +2689,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) // -- DM/Tag/CTF-spectator/etc -- // Order: DM->CTF->Coop - else if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF + else if ((gametyperules & GTR_DEATHMATCHSTARTS) || gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT))) { if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start @@ -2698,7 +2736,7 @@ mapthing_t *G_FindCTFStart(INT32 playernum) if (!numredctfstarts && !numbluectfstarts) //why even bother, eh? { - if (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer)) + if ((gametyperules & GTR_TEAMFLAGS) && (playernum == consoleplayer || (splitscreen && playernum == secondarydisplayplayer))) CONS_Alert(CONS_WARNING, M_GetText("No CTF starts in this map!\n")); return NULL; } @@ -3104,7 +3142,7 @@ void G_ExitLevel(void) CV_SetValue(&cv_teamscramble, cv_scrambleonchange.value); } - if (gametype != GT_COOP) + if (!(gametyperules & GTR_CAMPAIGN)) CONS_Printf(M_GetText("The round has ended.\n")); // Remove CEcho text on round end. @@ -3136,6 +3174,221 @@ const char *Gametype_Names[NUMGAMETYPES] = "CTF" // GT_CTF }; +// For dehacked +const char *Gametype_ConstantNames[NUMGAMETYPES] = +{ + "GT_COOP", // GT_COOP + "GT_COMPETITION", // GT_COMPETITION + "GT_RACE", // GT_RACE + + "GT_MATCH", // GT_MATCH + "GT_TEAMMATCH", // GT_TEAMMATCH + + "GT_TAG", // GT_TAG + "GT_HIDEANDSEEK", // GT_HIDEANDSEEK + + "GT_CTF" // GT_CTF +}; + +// Gametype rules +UINT32 gametypedefaultrules[NUMGAMETYPES] = +{ + // Co-op + GTR_CAMPAIGN|GTR_LIVES|GTR_SPAWNENEMIES|GTR_ALLOWEXIT|GTR_EMERALDHUNT|GTR_EMERALDTOKENS|GTR_SPECIALSTAGES, + // Competition + GTR_RACE|GTR_LIVES|GTR_SPAWNENEMIES|GTR_EMERALDTOKENS|GTR_SPAWNINVUL|GTR_ALLOWEXIT, + // Race + GTR_RACE|GTR_SPAWNENEMIES|GTR_SPAWNINVUL|GTR_ALLOWEXIT, + + // Match + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD|GTR_DEATHPENALTY, + // Team Match + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_SPAWNINVUL|GTR_PITYSHIELD, + + // Tag + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL, + // Hide and Seek + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_TAG|GTR_SPECTATORS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_HIDETIME|GTR_BLINDFOLDED|GTR_SPAWNINVUL, + + // CTF + GTR_RINGSLINGER|GTR_FIRSTPERSON|GTR_SPECTATORS|GTR_TEAMS|GTR_TEAMFLAGS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_MATCHEMERALDS|GTR_SPAWNINVUL|GTR_PITYSHIELD, +}; + +// +// G_SetGametype +// +// Set a new gametype, also setting gametype rules accordingly. Yay! +// +void G_SetGametype(INT16 gtype) +{ + gametype = gtype; + gametyperules = gametypedefaultrules[gametype]; +} + +// +// G_AddGametype +// +// Add a gametype. Returns the new gametype number. +// +INT16 G_AddGametype(UINT32 rules) +{ + INT16 newgtype = gametypecount; + gametypecount++; + + // Set gametype rules. + gametypedefaultrules[newgtype] = rules; + Gametype_Names[newgtype] = "???"; + + // Update gametype_cons_t accordingly. + G_UpdateGametypeSelections(); + + return newgtype; +} + +// +// G_AddGametypeConstant +// +// Self-explanatory. Filters out "bad" characters. +// +void G_AddGametypeConstant(INT16 gtype, const char *newgtconst) +{ + char *gtconst = Z_Malloc(strlen(newgtconst) + 3, PU_STATIC, NULL); + // Copy GT_ and the gametype name. + strcpy(gtconst, "GT_"); + strcat(gtconst, newgtconst); + // Make uppercase. + strupr(gtconst); + // Remove characters. +#define REMOVECHAR(chr) \ + { \ + char *chrfind = strchr(gtconst, chr); \ + while (chrfind) \ + { \ + *chrfind = '_'; \ + chrfind = strchr(chrfind, chr); \ + } \ + } + + // Space + REMOVECHAR(' ') + // Used for operations + REMOVECHAR('+') + REMOVECHAR('-') + REMOVECHAR('*') + REMOVECHAR('/') + REMOVECHAR('%') + REMOVECHAR('^') + // Part of Lua's syntax + REMOVECHAR('#') + REMOVECHAR('=') + REMOVECHAR('~') + REMOVECHAR('<') + REMOVECHAR('>') + REMOVECHAR('(') + REMOVECHAR(')') + REMOVECHAR('{') + REMOVECHAR('}') + REMOVECHAR('[') + REMOVECHAR(']') + REMOVECHAR(':') + REMOVECHAR(';') + REMOVECHAR(',') + REMOVECHAR('.') + +#undef REMOVECHAR + + // Finally, set the constant string. + Gametype_ConstantNames[gtype] = gtconst; +} + +// +// G_UpdateGametypeSelections +// +// Updates gametype_cons_t. +// +void G_UpdateGametypeSelections(void) +{ + INT32 i; + for (i = 0; i < gametypecount; i++) + { + gametype_cons_t[i].value = i; + gametype_cons_t[i].strvalue = Gametype_Names[i]; + } + gametype_cons_t[NUMGAMETYPES].value = 0; + gametype_cons_t[NUMGAMETYPES].strvalue = NULL; +} + +// +// G_SetGametypeDescription +// +// Set a description for the specified gametype. +// (Level platter) +// +void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolor, UINT8 rightcolor) +{ + if (descriptiontext != NULL) + strncpy(gametypedesc[gtype].notes, descriptiontext, 441); + gametypedesc[gtype].col[0] = leftcolor; + gametypedesc[gtype].col[1] = rightcolor; +} + +// Gametype rankings +INT16 gametyperankings[NUMGAMETYPES] = +{ + GT_COOP, + GT_COMPETITION, + GT_RACE, + + GT_MATCH, + GT_TEAMMATCH, + + GT_TAG, + GT_HIDEANDSEEK, + + GT_CTF, +}; + +// Gametype to TOL (Type Of Level) +UINT32 gametypetol[NUMGAMETYPES] = +{ + TOL_COOP, // Co-op + TOL_COMPETITION, // Competition + TOL_RACE, // Race + + TOL_MATCH, // Match + TOL_MATCH, // Team Match + + TOL_TAG, // Tag + TOL_TAG, // Hide and Seek + + TOL_CTF, // CTF +}; + +// +// G_AddTOL +// +// Adds a type of level. +// +void G_AddTOL(UINT32 newtol, const char *tolname) +{ + TYPEOFLEVEL[numtolinfo].name = Z_StrDup(tolname); + TYPEOFLEVEL[numtolinfo].flag = newtol; + numtolinfo++; + + TYPEOFLEVEL[numtolinfo].name = NULL; + TYPEOFLEVEL[numtolinfo].flag = 0; +} + +// +// G_AddTOL +// +// Assigns a type of level to a gametype. +// +void G_AddGametypeTOL(INT16 gtype, UINT32 newtol) +{ + gametypetol[gtype] = newtol; +} + // // G_GetGametypeByName // @@ -3178,8 +3431,8 @@ boolean G_IsSpecialStage(INT32 mapnum) // boolean G_GametypeUsesLives(void) { - // Coop, Competitive - if ((gametype == GT_COOP || gametype == GT_COMPETITION) + // Coop, Competitive + if ((gametyperules & GTR_LIVES) && !(modeattacking || metalrecording) // No lives in Time Attack && !G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)) // No lives in NiGHTS @@ -3195,7 +3448,7 @@ boolean G_GametypeUsesLives(void) // boolean G_GametypeHasTeams(void) { - return (gametype == GT_TEAMMATCH || gametype == GT_CTF); + return (gametyperules & GTR_TEAMS); } // @@ -3206,7 +3459,7 @@ boolean G_GametypeHasTeams(void) // boolean G_GametypeHasSpectators(void) { - return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE); + return (gametyperules & GTR_SPECTATORS); } // @@ -3217,7 +3470,7 @@ boolean G_GametypeHasSpectators(void) // boolean G_RingSlingerGametype(void) { - return ((gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE) || (cv_ringslinger.value)); + return ((gametyperules & GTR_RINGSLINGER) || (cv_ringslinger.value)); } // @@ -3227,7 +3480,7 @@ boolean G_RingSlingerGametype(void) // boolean G_PlatformGametype(void) { - return (gametype == GT_COOP || gametype == GT_RACE || gametype == GT_COMPETITION); + return (!(gametyperules & GTR_RINGSLINGER)); } // @@ -3237,7 +3490,7 @@ boolean G_PlatformGametype(void) // boolean G_TagGametype(void) { - return (gametype == GT_TAG || gametype == GT_HIDEANDSEEK); + return (gametyperules & GTR_TAG); } /** Get the typeoflevel flag needed to indicate support of a gametype. @@ -3248,18 +3501,9 @@ boolean G_TagGametype(void) */ INT16 G_TOLFlag(INT32 pgametype) { - if (!multiplayer) return TOL_SP; - if (pgametype == GT_COOP) return TOL_COOP; - if (pgametype == GT_COMPETITION) return TOL_COMPETITION; - if (pgametype == GT_RACE) return TOL_RACE; - if (pgametype == GT_MATCH) return TOL_MATCH; - if (pgametype == GT_TEAMMATCH) return TOL_MATCH; - if (pgametype == GT_TAG) return TOL_TAG; - if (pgametype == GT_HIDEANDSEEK) return TOL_TAG; - if (pgametype == GT_CTF) return TOL_CTF; - - CONS_Alert(CONS_ERROR, M_GetText("Unknown gametype! %d\n"), pgametype); - return INT16_MAX; + if (!multiplayer) + return TOL_SP; + return gametypetol[pgametype]; } /** Select a random map with the given typeoflevel flags. @@ -3270,7 +3514,7 @@ INT16 G_TOLFlag(INT32 pgametype) * has those flags. * \author Graue */ -static INT16 RandMap(INT16 tolflags, INT16 pprevmap) +static INT16 RandMap(UINT32 tolflags, INT16 pprevmap) { INT16 *okmaps = Z_Malloc(NUMMAPS * sizeof(INT16), PU_STATIC, NULL); INT32 numokmaps = 0; @@ -3428,10 +3672,10 @@ static void G_DoCompleted(void) I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1); // wrap around in race - if (nextmap >= 1100-1 && nextmap <= 1102-1 && (gametype == GT_RACE || gametype == GT_COMPETITION)) + if (nextmap >= 1100-1 && nextmap <= 1102-1 && !(gametyperules & GTR_CAMPAIGN)) nextmap = (INT16)(spstage_start-1); - if ((gottoken = (gametype == GT_COOP && token))) + if ((gottoken = ((gametyperules & GTR_SPECIALSTAGES) && token))) { token--; @@ -3451,7 +3695,7 @@ static void G_DoCompleted(void) automapactive = false; - if (gametype != GT_COOP) + if (!(gametyperules & GTR_CAMPAIGN)) { if (cv_advancemap.value == 0) // Stay on same map. nextmap = prevmap; diff --git a/src/g_game.h b/src/g_game.h index c19faebe4..238dd1964 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -143,6 +143,7 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, void G_DoLoadLevel(boolean resetplayer); void G_StartTitleCard(void); void G_PreLevelTitleCard(void); +boolean G_IsTitleCardAvailable(void); void G_DeferedPlayDemo(const char *demo); // Can be called by the startup code or M_Responder, calls P_SetupLevel. @@ -202,6 +203,18 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill); void G_StopDemo(void); boolean G_CheckDemoStatus(void); +extern UINT32 gametypedefaultrules[NUMGAMETYPES]; +extern UINT32 gametypetol[NUMGAMETYPES]; +extern INT16 gametyperankings[NUMGAMETYPES]; + +void G_SetGametype(INT16 gametype); +INT16 G_AddGametype(UINT32 rules); +void G_AddGametypeConstant(INT16 gtype, const char *newgtconst); +void G_UpdateGametypeSelections(void); +void G_AddTOL(UINT32 newtol, const char *tolname); +void G_AddGametypeTOL(INT16 gtype, UINT32 newtol); +void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolor, UINT8 rightcolor); + INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 313c62eec..dfecbea85 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -112,13 +112,11 @@ typedef struct FLOAT fovxangle, fovyangle; UINT8 splitscreen; boolean flip; // screenflip -#ifdef ROTSPRITE boolean roll; SINT8 rollflip; FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ UINT8 rotaxis; FLOAT centerx, centery; -#endif #ifdef USE_FTRANSFORM_MIRROR boolean mirror; // SRB2Kart: Encore Mode #endif diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 7fd214a29..1cfa1a2e8 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5118,17 +5118,12 @@ static void HWR_ProjectSprite(mobj_t *thing) fixed_t spr_offset, spr_topoffset; #ifdef ROTSPRITE patch_t *rotsprite = NULL; - angle_t arollangle; - UINT32 rollangle; + INT32 rollangle = 0; #endif if (!thing) return; -#ifdef ROTSPRITE - arollangle = thing->rollangle; - rollangle = AngleFixed(arollangle)>>FRACBITS; -#endif this_scale = FIXED_TO_FLOAT(thing->scale); // transform the origin point @@ -5235,11 +5230,11 @@ static void HWR_ProjectSprite(mobj_t *thing) spr_topoffset = spritecachedinfo[lumpoff].topoffset; #ifdef ROTSPRITE - if (rollangle > 0) + if (thing->rollangle) { + rollangle = R_GetRollAngle(thing->rollangle); if (!sprframe->rotsprite.cached[rot]) R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip); - rollangle /= ROTANGDIFF; rotsprite = sprframe->rotsprite.patch[rot][rollangle]; if (rotsprite != NULL) { diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 0591f9b8f..02e8df9a3 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1197,10 +1197,8 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP)); spritedef_t *sprdef; spriteframe_t *sprframe; -#ifdef ROTSPRITE spriteinfo_t *sprinfo; angle_t ang; -#endif INT32 mod; float finalscale; @@ -1224,16 +1222,12 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) { md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins]; md2->skin = (skin_t*)spr->mobj->skin-skins; -#ifdef ROTSPRITE sprinfo = &((skin_t *)spr->mobj->skin)->sprinfo[spr->mobj->sprite2]; -#endif } else { md2 = &md2_models[spr->mobj->sprite]; -#ifdef ROTSPRITE sprinfo = &spriteinfo[spr->mobj->sprite]; -#endif } if (md2->error) @@ -1433,9 +1427,8 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) p.angley = FIXED_TO_FLOAT(anglef); } -#ifdef ROTSPRITE p.rollangle = 0.0f; - p.rollflip = 0; + p.rollflip = 1; p.rotaxis = 0; if (spr->mobj->rollangle) { @@ -1458,7 +1451,6 @@ boolean HWR_DrawModel(gr_vissprite_t *spr) else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left p.rollflip = -1; } -#endif p.anglex = 0.0f; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 6997ebcfe..5689d7945 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2628,7 +2628,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f); -#ifdef ROTSPRITE if (pos->roll) { float roll = (1.0f * pos->rollflip); @@ -2641,7 +2640,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglRotatef(pos->rollangle, roll, 0.0f, 0.0f); pglTranslatef(-pos->centerx, -pos->centery, 0); } -#endif pglScalef(scalex, scaley, scalez); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 91a167a60..d9801793b 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2066,7 +2066,7 @@ static void HU_drawGametype(void) { const char *strvalue = NULL; - if (gametype < 0 || gametype >= NUMGAMETYPES) + if (gametype < 0 || gametype >= gametypecount) return; // not a valid gametype??? strvalue = Gametype_Names[gametype]; @@ -2371,7 +2371,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I for (i = 0; i < scorelines; i++) { - if (players[tab[i].num].spectator && gametype != GT_COOP) + if (players[tab[i].num].spectator && gametyperankings[gametype] != GT_COOP) continue; //ignore them. greycheck = greycheckdef; @@ -2434,7 +2434,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I } } - if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives + if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives)); else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) { @@ -2447,7 +2447,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I if (players[tab[i].num].exiting || (players[tab[i].num].pflags & PF_FINISHED)) V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); - if (gametype == GT_RACE) + if (gametyperankings[gametype] == GT_RACE) { if (circuitmap) { @@ -2541,7 +2541,7 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) | (greycheck ? 0 : V_TRANSLUCENT) | V_ALLOWLOWERCASE, name); - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) { if (players[tab[i].num].gotflag & GF_REDFLAG) // Red V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, rflagico, 0); @@ -2669,7 +2669,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) | (greycheck ? V_TRANSLUCENT : 0) | V_ALLOWLOWERCASE, name); - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) { if (players[tab[i].num].gotflag & GF_REDFLAG) // Red V_DrawSmallScaledPatch(x-28, y-4, 0, rflagico); @@ -2726,7 +2726,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline for (i = 0; i < scorelines; i++) { - if (players[tab[i].num].spectator && gametype != GT_COOP) + if (players[tab[i].num].spectator && gametyperankings[gametype] != GT_COOP) continue; //ignore them. greycheck = greycheckdef; @@ -2743,7 +2743,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline | (greycheck ? V_TRANSLUCENT : 0) | V_ALLOWLOWERCASE, name); - if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives + if (G_GametypeUsesLives() && !(gametyperankings[gametype] == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives)); else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) V_DrawSmallScaledPatch(x-28, y-4, 0, tagico); @@ -2792,7 +2792,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline } // All data drawn with thin string for space. - if (gametype == GT_RACE) + if (gametyperankings[gametype] == GT_RACE) { if (circuitmap) { @@ -2832,7 +2832,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor for (i = 0; i < scorelines; i++) { - if (players[tab[i].num].spectator && gametype != GT_COOP) + if (players[tab[i].num].spectator && gametyperankings[gametype] != GT_COOP) continue; //ignore them. greycheck = greycheckdef; @@ -2902,7 +2902,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor } // All data drawn with thin string for space. - if (gametype == GT_RACE) + if (gametyperankings[gametype] == GT_RACE) { if (circuitmap) { @@ -3026,21 +3026,21 @@ static void HU_DrawRankings(void) // draw the current gametype in the lower right HU_drawGametype(); - if (gametype != GT_RACE && gametype != GT_COMPETITION && gametype != GT_COOP) + if (gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT)) { - if (cv_timelimit.value && timelimitintics > 0) + if ((gametyperules & GTR_TIMELIMIT) && cv_timelimit.value && timelimitintics > 0) { V_DrawCenteredString(64, 8, 0, "TIME"); V_DrawCenteredString(64, 16, 0, va("%i:%02i", G_TicsToMinutes(stplyr->realtime, true), G_TicsToSeconds(stplyr->realtime))); } - if (cv_pointlimit.value > 0) + if ((gametyperules & GTR_POINTLIMIT) && cv_pointlimit.value > 0) { V_DrawCenteredString(256, 8, 0, "POINT LIMIT"); V_DrawCenteredString(256, 16, 0, va("%d", cv_pointlimit.value)); } } - else if (gametype == GT_COOP) + else if (gametyperankings[gametype] == GT_COOP) { INT32 totalscore = 0; for (i = 0; i < MAXPLAYERS; i++) @@ -3074,7 +3074,7 @@ static void HU_DrawRankings(void) tab[i].num = -1; tab[i].name = 0; - if (gametype == GT_RACE && !circuitmap) + if (gametyperankings[gametype] == GT_RACE && !circuitmap) tab[i].count = INT32_MAX; } @@ -3083,7 +3083,7 @@ static void HU_DrawRankings(void) if (!playeringame[j]) continue; - if (gametype != GT_COOP && players[j].spectator) + if (!G_PlatformGametype() && players[j].spectator) continue; for (i = 0; i < MAXPLAYERS; i++) @@ -3091,10 +3091,10 @@ static void HU_DrawRankings(void) if (!playeringame[i]) continue; - if (gametype != GT_COOP && players[i].spectator) + if (!G_PlatformGametype() && players[i].spectator) continue; - if (gametype == GT_RACE) + if (gametyperankings[gametype] == GT_RACE) { if (circuitmap) { @@ -3117,7 +3117,7 @@ static void HU_DrawRankings(void) } } } - else if (gametype == GT_COMPETITION) + else if (gametyperankings[gametype] == GT_COMPETITION) { // todo put something more fitting for the gametype here, such as current // number of categories led diff --git a/src/info.h b/src/info.h index 26fb1738d..261abbac5 100644 --- a/src/info.h +++ b/src/info.h @@ -155,11 +155,9 @@ void A_SpawnObjectAbsolute(); void A_SpawnObjectRelative(); void A_ChangeAngleRelative(); void A_ChangeAngleAbsolute(); -#ifdef ROTSPRITE void A_RollAngle(); void A_ChangeRollAngleRelative(); void A_ChangeRollAngleAbsolute(); -#endif void A_PlaySound(); void A_FindTarget(); void A_FindTracer(); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 018529722..695e9367e 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -12,6 +12,7 @@ #include "doomdef.h" #ifdef HAVE_BLUA +#include "fastcmp.h" #include "p_local.h" #include "p_setup.h" // So we can have P_SetupLevelSky #ifdef ESLOPE @@ -23,6 +24,8 @@ #include "m_random.h" #include "s_sound.h" #include "g_game.h" +#include "m_menu.h" +#include "y_inter.h" #include "hu_stuff.h" // HU_AddChatText #include "console.h" #include "d_netcmd.h" // IsPlayerAdmin @@ -144,10 +147,8 @@ static const struct { {META_MOBJINFO, "mobjinfo_t"}, {META_SFXINFO, "sfxinfo_t"}, {META_SPRITEINFO, "spriteinfo_t"}, -#ifdef ROTSPRITE {META_PIVOTLIST, "spriteframepivot_t[]"}, {META_FRAMEPIVOT, "spriteframepivot_t"}, -#endif {META_MOBJ, "mobj_t"}, {META_MAPTHING, "mapthing_t"}, @@ -2632,6 +2633,145 @@ static int lib_sStartMusicCaption(lua_State *L) // G_GAME //////////// +// Copypasted from lib_cvRegisterVar :] +static int lib_gAddGametype(lua_State *L) +{ + const char *k; + lua_Integer i; + + const char *gtname = NULL; + const char *gtconst = NULL; + const char *gtdescription = NULL; + INT16 newgtidx = 0; + UINT32 newgtrules = 0; + UINT32 newgttol = 0; + INT32 newgtpointlimit = 0; + INT32 newgttimelimit = 0; + UINT8 newgtleftcolor = 0; + UINT8 newgtrightcolor = 0; + INT16 newgtrankingstype = -1; + int newgtinttype = 0; + + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one. + + if (!lua_lumploading) + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); + + // Ran out of gametype slots + if (gametypecount == NUMGAMETYPEFREESLOTS) + return luaL_error(L, "Ran out of free gametype slots!"); + +#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("G_AddGametype") " (%s)", e); +#define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1))) + + lua_pushnil(L); + while (lua_next(L, 1)) { + // stack: gametype table, key/index, value + // 1 2 3 + i = 0; + k = NULL; + if (lua_isnumber(L, 2)) + i = lua_tointeger(L, 2); + else if (lua_isstring(L, 2)) + k = lua_tostring(L, 2); + + // Sorry, no gametype rules as key names. + if (i == 1 || (k && fasticmp(k, "name"))) { + if (!lua_isstring(L, 3)) + TYPEERROR("name", LUA_TSTRING) + gtname = Z_StrDup(lua_tostring(L, 3)); + } else if (i == 2 || (k && fasticmp(k, "identifier"))) { + if (!lua_isstring(L, 3)) + TYPEERROR("identifier", LUA_TSTRING) + gtconst = Z_StrDup(lua_tostring(L, 3)); + } else if (i == 3 || (k && fasticmp(k, "rules"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("rules", LUA_TNUMBER) + newgtrules = (UINT32)lua_tointeger(L, 3); + } else if (i == 4 || (k && fasticmp(k, "typeoflevel"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("typeoflevel", LUA_TNUMBER) + newgttol = (UINT32)lua_tointeger(L, 3); + } else if (i == 5 || (k && fasticmp(k, "rankingtype"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("rankingtype", LUA_TNUMBER) + newgtrankingstype = (INT16)lua_tointeger(L, 3); + } else if (i == 6 || (k && fasticmp(k, "intermissiontype"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("intermissiontype", LUA_TNUMBER) + newgtinttype = (int)lua_tointeger(L, 3); + } else if (i == 7 || (k && fasticmp(k, "defaultpointlimit"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("defaultpointlimit", LUA_TNUMBER) + newgtpointlimit = (INT32)lua_tointeger(L, 3); + } else if (i == 8 || (k && fasticmp(k, "defaulttimelimit"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("defaulttimelimit", LUA_TNUMBER) + newgttimelimit = (INT32)lua_tointeger(L, 3); + } else if (i == 9 || (k && fasticmp(k, "description"))) { + if (!lua_isstring(L, 3)) + TYPEERROR("description", LUA_TSTRING) + gtdescription = Z_StrDup(lua_tostring(L, 3)); + } else if (i == 10 || (k && fasticmp(k, "headerleftcolor"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("headerleftcolor", LUA_TNUMBER) + newgtleftcolor = (UINT8)lua_tointeger(L, 3); + } else if (i == 11 || (k && fasticmp(k, "headerrightcolor"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("headerrightcolor", LUA_TNUMBER) + newgtrightcolor = (UINT8)lua_tointeger(L, 3); + // Key name specified + } else if ((!i) && (k && fasticmp(k, "headercolor"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("headercolor", LUA_TNUMBER) + newgtleftcolor = newgtrightcolor = (UINT8)lua_tointeger(L, 3); + } + lua_pop(L, 1); + } + +#undef FIELDERROR +#undef TYPEERROR + + // pop gametype table + lua_pop(L, 1); + + // Set defaults + if (gtname == NULL) + gtname = Z_StrDup("Unnamed gametype"); + if (gtdescription == NULL) + gtdescription = Z_StrDup("???"); + + // Add the new gametype + newgtidx = G_AddGametype(newgtrules); + G_AddGametypeTOL(newgtidx, newgttol); + G_SetGametypeDescription(newgtidx, NULL, newgtleftcolor, newgtrightcolor); + strncpy(gametypedesc[newgtidx].notes, gtdescription, 441); + + // Not covered by G_AddGametype alone. + if (newgtrankingstype == -1) + newgtrankingstype = newgtidx; + gametyperankings[newgtidx] = newgtrankingstype; + intermissiontypes[newgtidx] = newgtinttype; + pointlimits[newgtidx] = newgtpointlimit; + timelimits[newgtidx] = newgttimelimit; + + // Write the new gametype name. + Gametype_Names[newgtidx] = gtname; + + // Write the constant name. + if (gtconst == NULL) + gtconst = gtname; + G_AddGametypeConstant(newgtidx, gtconst); + + // Update gametype_cons_t accordingly. + G_UpdateGametypeSelections(); + + // done + CONS_Printf("Added gametype %s\n", Gametype_Names[newgtidx]); + return 0; +} + static int lib_gBuildMapName(lua_State *L) { INT32 map = luaL_optinteger(L, 1, gamemap); @@ -2991,6 +3131,7 @@ static luaL_Reg lib[] = { {"S_StartMusicCaption", lib_sStartMusicCaption}, // g_game + {"G_AddGametype", lib_gAddGametype}, {"G_BuildMapName",lib_gBuildMapName}, {"G_DoReborn",lib_gDoReborn}, {"G_SetCustomExitVars",lib_gSetCustomExitVars}, diff --git a/src/lua_hook.h b/src/lua_hook.h index 6617bca93..68efbce93 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -51,6 +51,8 @@ enum hook { hook_PlayerCanDamage, hook_PlayerQuit, hook_IntermissionThinker, + hook_TeamSwitch, + hook_ViewpointSwitch, hook_MAX // last hook }; @@ -93,5 +95,7 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAft UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting void LUAh_IntermissionThinker(void); // Hook for Y_Ticker +boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... +UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index ef87d0b6f..91b4c6992 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -62,6 +62,8 @@ const char *const hookNames[hook_MAX+1] = { "PlayerCanDamage", "PlayerQuit", "IntermissionThinker", + "TeamSwitch", + "ViewpointSwitch", NULL }; @@ -203,6 +205,8 @@ static int lib_addHook(lua_State *L) case hook_PlayerSpawn: case hook_FollowMobj: case hook_PlayerCanDamage: + case hook_TeamSwitch: + case hook_ViewpointSwitch: case hook_ShieldSpawn: case hook_ShieldSpecial: lastp = &playerhooks; @@ -657,14 +661,16 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ); lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 0)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); @@ -745,14 +751,16 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ); lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 0)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); @@ -823,13 +831,15 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 LUA_PushUserdata(gL, target, META_MOBJ); LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damagetype); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 0)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); @@ -1346,4 +1356,101 @@ void LUAh_IntermissionThinker(void) } } +// Hook for team switching +// It's just an edit of LUAh_ViewpointSwitch. +boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble) +{ + hook_p hookp; + boolean canSwitchTeam = true; + if (!gL || !(hooksAvailable[hook_TeamSwitch/8] & (1<<(hook_TeamSwitch%8)))) + return true; + + lua_settop(gL, 0); + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_TeamSwitch) + continue; + + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, player, META_PLAYER); + lua_pushinteger(gL, newteam); + lua_pushboolean(gL, fromspectators); + lua_pushboolean(gL, tryingautobalance); + lua_pushboolean(gL, tryingscramble); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) + canSwitchTeam = false; // Can't switch team + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return canSwitchTeam; +} + +// Hook for spy mode +UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced) +{ + hook_p hookp; + UINT8 canSwitchView = 0; // 0 = default, 1 = force yes, 2 = force no. + if (!gL || !(hooksAvailable[hook_ViewpointSwitch/8] & (1<<(hook_ViewpointSwitch%8)))) + return 0; + + lua_settop(gL, 0); + hud_running = true; + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_ViewpointSwitch) + continue; + + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, newdisplayplayer, META_PLAYER); + lua_pushboolean(gL, forced); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + if (lua_pcall(gL, 3, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave canSwitchView = 0. + if (lua_toboolean(gL, -1)) + canSwitchView = 1; // Force viewpoint switch + else + canSwitchView = 2; // Skip viewpoint switch + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + hud_running = false; + + return canSwitchView; +} + #endif diff --git a/src/lua_hud.h b/src/lua_hud.h index 23e3ef834..a00a5cb02 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -34,6 +34,9 @@ enum hud { hud_coopemeralds, hud_tokens, hud_tabemblems, + // Intermission + hud_intermissiontally, + hud_intermissionmessages, hud_MAX }; @@ -44,4 +47,5 @@ boolean LUA_HudEnabled(enum hud option); void LUAh_GameHUD(player_t *stplyr); void LUAh_ScoresHUD(void); void LUAh_TitleHUD(void); -void LUAh_TitleCardHUD(player_t *stplyr); +void LUAh_TitleCardHUD(player_t *stplayr); +void LUAh_IntermissionHUD(void); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 5b5aa3b4b..12ae1b5fc 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -61,6 +61,9 @@ static const char *const hud_disable_options[] = { "coopemeralds", "tokens", "tabemblems", + + "intermissiontally", + "intermissionmessages", NULL}; enum hudinfo { @@ -93,12 +96,14 @@ static const char *const patch_opt[] = { enum hudhook { hudhook_game = 0, hudhook_scores, + hudhook_intermission, hudhook_title, hudhook_titlecard }; static const char *const hudhook_opt[] = { "game", "scores", + "intermission", "title", "titlecard", NULL}; @@ -1051,13 +1056,16 @@ int LUA_HudLib(lua_State *L) lua_rawseti(L, -2, 2); // HUD[2] = game rendering functions array lua_newtable(L); - lua_rawseti(L, -2, 3); // HUD[2] = scores rendering functions array + lua_rawseti(L, -2, 3); // HUD[3] = scores rendering functions array lua_newtable(L); - lua_rawseti(L, -2, 4); // HUD[3] = title rendering functions array + lua_rawseti(L, -2, 4); // HUD[4] = intermission rendering functions array lua_newtable(L); - lua_rawseti(L, -2, 5); // HUD[4] = title card rendering functions array + lua_rawseti(L, -2, 5); // HUD[5] = title rendering functions array + + lua_newtable(L); + lua_rawseti(L, -2, 6); // HUD[6] = title card rendering functions array lua_setfield(L, LUA_REGISTRYINDEX, "HUD"); luaL_newmetatable(L, META_HUDINFO); @@ -1229,4 +1237,29 @@ void LUAh_TitleCardHUD(player_t *stplayr) hud_running = false; } +void LUAh_IntermissionHUD(void) +{ + if (!gL || !(hudAvailable & (1<angle); break; -#ifdef ROTSPRITE case mobj_rollangle: lua_pushangle(L, mo->rollangle); break; -#endif case mobj_sprite: lua_pushinteger(L, mo->sprite); break; @@ -462,11 +456,9 @@ static int mobj_set(lua_State *L) else if (mo->player == &players[secondarydisplayplayer]) localangle2 = mo->angle; break; -#ifdef ROTSPRITE case mobj_rollangle: mo->rollangle = luaL_checkangle(L, 3); break; -#endif case mobj_sprite: mo->sprite = luaL_checkinteger(L, 3); break; diff --git a/src/lua_script.c b/src/lua_script.c index fe3c2f10d..18d9a87c2 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -18,7 +18,9 @@ #include "w_wad.h" #include "p_setup.h" #include "r_state.h" +#include "r_sky.h" #include "g_game.h" +#include "f_finale.h" #include "byteptr.h" #include "p_saveg.h" #include "p_local.h" @@ -79,8 +81,239 @@ FUNCNORETURN static int LUA_Panic(lua_State *L) #endif } +// Moved here from lib_getenum. +int LUA_PushGlobals(lua_State *L, const char *word) +{ + if (fastcmp(word,"gamemap")) { + lua_pushinteger(L, gamemap); + return 1; + } else if (fastcmp(word,"maptol")) { + lua_pushinteger(L, maptol); + return 1; + } else if (fastcmp(word,"ultimatemode")) { + lua_pushboolean(L, ultimatemode != 0); + return 1; + } else if (fastcmp(word,"mariomode")) { + lua_pushboolean(L, mariomode != 0); + return 1; + } else if (fastcmp(word,"twodlevel")) { + lua_pushboolean(L, twodlevel != 0); + return 1; + } else if (fastcmp(word,"circuitmap")) { + lua_pushboolean(L, circuitmap); + return 1; + } else if (fastcmp(word,"netgame")) { + lua_pushboolean(L, netgame); + return 1; + } else if (fastcmp(word,"multiplayer")) { + lua_pushboolean(L, multiplayer); + return 1; + } else if (fastcmp(word,"modeattacking")) { + lua_pushboolean(L, modeattacking); + return 1; + } else if (fastcmp(word,"splitscreen")) { + lua_pushboolean(L, splitscreen); + return 1; + } else if (fastcmp(word,"gamecomplete")) { + lua_pushboolean(L, gamecomplete); + return 1; + } else if (fastcmp(word,"devparm")) { + lua_pushboolean(L, devparm); + return 1; + } else if (fastcmp(word,"modifiedgame")) { + lua_pushboolean(L, modifiedgame && !savemoddata); + return 1; + } else if (fastcmp(word,"menuactive")) { + lua_pushboolean(L, menuactive); + return 1; + } else if (fastcmp(word,"paused")) { + lua_pushboolean(L, paused); + return 1; + } else if (fastcmp(word,"bluescore")) { + lua_pushinteger(L, bluescore); + return 1; + } else if (fastcmp(word,"redscore")) { + lua_pushinteger(L, redscore); + return 1; + } else if (fastcmp(word,"timelimit")) { + lua_pushinteger(L, cv_timelimit.value); + return 1; + } else if (fastcmp(word,"pointlimit")) { + lua_pushinteger(L, cv_pointlimit.value); + return 1; + // begin map vars + } else if (fastcmp(word,"spstage_start")) { + lua_pushinteger(L, spstage_start); + return 1; + } else if (fastcmp(word,"sstage_start")) { + lua_pushinteger(L, sstage_start); + return 1; + } else if (fastcmp(word,"sstage_end")) { + lua_pushinteger(L, sstage_end); + return 1; + } else if (fastcmp(word,"smpstage_start")) { + lua_pushinteger(L, smpstage_start); + return 1; + } else if (fastcmp(word,"smpstage_end")) { + lua_pushinteger(L, smpstage_end); + return 1; + } else if (fastcmp(word,"titlemap")) { + lua_pushinteger(L, titlemap); + return 1; + } else if (fastcmp(word,"titlemapinaction")) { + lua_pushboolean(L, (titlemapinaction != TITLEMAP_OFF)); + return 1; + } else if (fastcmp(word,"bootmap")) { + lua_pushinteger(L, bootmap); + return 1; + } else if (fastcmp(word,"tutorialmap")) { + lua_pushinteger(L, tutorialmap); + return 1; + } else if (fastcmp(word,"tutorialmode")) { + lua_pushboolean(L, tutorialmode); + return 1; + // end map vars + // begin CTF colors + } else if (fastcmp(word,"skincolor_redteam")) { + lua_pushinteger(L, skincolor_redteam); + return 1; + } else if (fastcmp(word,"skincolor_blueteam")) { + lua_pushinteger(L, skincolor_blueteam); + return 1; + } else if (fastcmp(word,"skincolor_redring")) { + lua_pushinteger(L, skincolor_redring); + return 1; + } else if (fastcmp(word,"skincolor_bluering")) { + lua_pushinteger(L, skincolor_bluering); + return 1; + // end CTF colors + // begin timers + } else if (fastcmp(word,"invulntics")) { + lua_pushinteger(L, invulntics); + return 1; + } else if (fastcmp(word,"sneakertics")) { + lua_pushinteger(L, sneakertics); + return 1; + } else if (fastcmp(word,"flashingtics")) { + lua_pushinteger(L, flashingtics); + return 1; + } else if (fastcmp(word,"tailsflytics")) { + lua_pushinteger(L, tailsflytics); + return 1; + } else if (fastcmp(word,"underwatertics")) { + lua_pushinteger(L, underwatertics); + return 1; + } else if (fastcmp(word,"spacetimetics")) { + lua_pushinteger(L, spacetimetics); + return 1; + } else if (fastcmp(word,"extralifetics")) { + lua_pushinteger(L, extralifetics); + return 1; + } else if (fastcmp(word,"nightslinktics")) { + lua_pushinteger(L, nightslinktics); + return 1; + } else if (fastcmp(word,"gameovertics")) { + lua_pushinteger(L, gameovertics); + return 1; + } else if (fastcmp(word,"ammoremovaltics")) { + lua_pushinteger(L, ammoremovaltics); + return 1; + // end timers + } else if (fastcmp(word,"gametype")) { + lua_pushinteger(L, gametype); + return 1; + } else if (fastcmp(word,"gametyperules")) { + lua_pushinteger(L, gametyperules); + return 1; + } else if (fastcmp(word,"leveltime")) { + lua_pushinteger(L, leveltime); + return 1; + } else if (fastcmp(word,"sstimer")) { + lua_pushinteger(L, sstimer); + return 1; + } else if (fastcmp(word,"curWeather")) { + lua_pushinteger(L, curWeather); + return 1; + } else if (fastcmp(word,"globalweather")) { + lua_pushinteger(L, globalweather); + return 1; + } else if (fastcmp(word,"levelskynum")) { + lua_pushinteger(L, levelskynum); + return 1; + } else if (fastcmp(word,"globallevelskynum")) { + lua_pushinteger(L, globallevelskynum); + return 1; + } else if (fastcmp(word,"mapmusname")) { + lua_pushstring(L, mapmusname); + return 1; + } else if (fastcmp(word,"mapmusflags")) { + lua_pushinteger(L, mapmusflags); + return 1; + } else if (fastcmp(word,"mapmusposition")) { + lua_pushinteger(L, mapmusposition); + return 1; + // local player variables, by popular request + } else if (fastcmp(word,"consoleplayer")) { // player controlling console (aka local player 1) + if (consoleplayer < 0 || !playeringame[consoleplayer]) + return 0; + LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER); + return 1; + } else if (fastcmp(word,"displayplayer")) { // player visible on screen (aka display player 1) + if (displayplayer < 0 || !playeringame[displayplayer]) + return 0; + LUA_PushUserdata(L, &players[displayplayer], META_PLAYER); + return 1; + } else if (fastcmp(word,"secondarydisplayplayer")) { // local/display player 2, for splitscreen + if (!splitscreen || secondarydisplayplayer < 0 || !playeringame[secondarydisplayplayer]) + return 0; + LUA_PushUserdata(L, &players[secondarydisplayplayer], META_PLAYER); + return 1; + // end local player variables + } else if (fastcmp(word,"server")) { + if ((!multiplayer || !netgame) && !playeringame[serverplayer]) + return 0; + LUA_PushUserdata(L, &players[serverplayer], META_PLAYER); + return 1; + } else if (fastcmp(word,"admin")) { // BACKWARDS COMPATIBILITY HACK: This was replaced with IsPlayerAdmin(), but some 2.1 Lua scripts still use the admin variable. It now points to the first admin player in the array. + LUA_Deprecated(L, "admin", "IsPlayerAdmin(player)"); + if (!playeringame[adminplayers[0]] || IsPlayerAdmin(serverplayer)) + return 0; + LUA_PushUserdata(L, &players[adminplayers[0]], META_PLAYER); + return 1; + } else if (fastcmp(word,"emeralds")) { + lua_pushinteger(L, emeralds); + return 1; + } else if (fastcmp(word,"gravity")) { + lua_pushinteger(L, gravity); + return 1; + } else if (fastcmp(word,"VERSIONSTRING")) { + lua_pushstring(L, VERSIONSTRING); + return 1; + } else if (fastcmp(word, "token")) { + lua_pushinteger(L, token); + return 1; + } + return 0; +} + +// See the above. +int LUA_CheckGlobals(lua_State *L, const char *word) +{ + if (fastcmp(word, "gametyperules")) + gametyperules = (UINT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "redscore")) + redscore = (UINT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "bluescore")) + bluescore = (UINT32)luaL_checkinteger(L, 2); + else + return 0; + + // Global variable set, so return and don't error. + return 1; +} + // This function decides which global variables you are allowed to set. -static int noglobals(lua_State *L) +static int setglobals(lua_State *L) { const char *csname; char *name; @@ -106,6 +339,9 @@ static int noglobals(lua_State *L) return 0; } + if (LUA_CheckGlobals(L, csname)) + return 0; + Z_Free(name); return luaL_error(L, "Implicit global " LUA_QS " prevented. Create a local variable instead.", csname); } @@ -144,7 +380,7 @@ static void LUA_ClearState(void) // lock the global namespace lua_getmetatable(L, LUA_GLOBALSINDEX); - lua_pushcfunction(L, noglobals); + lua_pushcfunction(L, setglobals); lua_setfield(L, -2, "__newindex"); lua_newtable(L); lua_setfield(L, -2, "__metatable"); diff --git a/src/lua_script.h b/src/lua_script.h index 4f66d3f8a..8f27dcb4c 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -54,6 +54,8 @@ void LUA_InvalidatePlayer(player_t *player); void LUA_Step(void); void LUA_Archive(void); void LUA_UnArchive(void); +int LUA_PushGlobals(lua_State *L, const char *word); +int LUA_CheckGlobals(lua_State *L, const char *word); void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c void LUA_CVarChanged(const char *name); // lua_consolelib.c int Lua_optoption(lua_State *L, int narg, diff --git a/src/m_cheat.c b/src/m_cheat.c index 3d1fe5b7e..bd6eca73a 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -778,7 +778,7 @@ void Command_CauseCfail_f(void) P_SetThingPosition(players[consoleplayer].mo); // CTF consistency test - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) { if (blueflag) { P_RemoveMobj(blueflag); diff --git a/src/m_menu.c b/src/m_menu.c index b62813db6..b3ff8ce71 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -605,7 +605,7 @@ static menuitem_t MISC_ChangeTeamMenu[] = {IT_WHITESTRING|IT_CALL, NULL, "Confirm", M_ConfirmTeamChange, 90}, }; -static const gtdesc_t gametypedesc[] = +gtdesc_t gametypedesc[NUMGAMETYPES] = { {{ 54, 54}, "Play through the single-player campaign with your friends, teaming up to beat Dr Eggman's nefarious challenges!"}, {{103, 103}, "Speed your way through the main acts, competing in several different categories to see who's the best."}, @@ -1181,7 +1181,8 @@ static menuitem_t OP_CameraOptionsMenu[] = {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Distance", &cv_cam_dist, 60}, {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Height", &cv_cam_height, 70}, - {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Speed", &cv_cam_speed, 80}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Spacial Speed", &cv_cam_speed, 80}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Turning Speed", &cv_cam_turnmultiplier, 90}, {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 100}, }; @@ -1195,7 +1196,8 @@ static menuitem_t OP_Camera2OptionsMenu[] = {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Distance", &cv_cam2_dist, 60}, {IT_STRING | IT_CVAR | IT_CV_INTEGERSTEP, NULL, "Camera Height", &cv_cam2_height, 70}, - {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Speed", &cv_cam2_speed, 80}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Spacial Speed", &cv_cam2_speed, 80}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Camera Turning Speed", &cv_cam2_turnmultiplier, 90}, {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 100}, }; @@ -4688,6 +4690,9 @@ static boolean M_CanShowLevelOnPlatter(INT32 mapnum, INT32 gt) if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) return true; + if (gt > 0 && gt < gametypecount && (mapheaderinfo[mapnum]->typeoflevel & gametypetol[gt])) + return true; + return false; case LLM_LEVELSELECT: @@ -9936,7 +9941,7 @@ static void M_DrawConnectMenu(void) va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time))); gt = "Unknown"; - if (serverlist[slindex].info.gametype < NUMGAMETYPES) + if (serverlist[slindex].info.gametype < gametypecount) gt = Gametype_Names[serverlist[slindex].info.gametype]; V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags, diff --git a/src/m_menu.h b/src/m_menu.h index ce9b422dc..19858e2fc 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -371,6 +371,7 @@ typedef struct UINT8 col[2]; char notes[441]; } gtdesc_t; +extern gtdesc_t gametypedesc[NUMGAMETYPES]; // mode descriptions for video mode menu typedef struct diff --git a/src/m_misc.c b/src/m_misc.c index 138a25ab1..15d0a27e1 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -2466,3 +2466,92 @@ const char *M_FileError(FILE *fp) else return "end-of-file"; } + +/** Return the number of parts of this path. +*/ +int M_PathParts(const char *path) +{ + int n; + const char *p; + const char *t; + for (n = 0, p = path ;; ++n) + { + t = p; + if (( p = strchr(p, PATHSEP[0]) )) + p += strspn(p, PATHSEP); + else + { + if (*t)/* there is something after the final delimiter */ + n++; + break; + } + } + return n; +} + +/** Check whether a path is an absolute path. +*/ +boolean M_IsPathAbsolute(const char *path) +{ +#ifdef _WIN32 + return ( strncmp(&path[1], ":\\", 2) == 0 ); +#else + return ( path[0] == '/' ); +#endif +} + +/** I_mkdir for each part of the path. +*/ +void M_MkdirEachUntil(const char *cpath, int start, int end, int mode) +{ + char path[MAX_WADPATH]; + char *p; + char *t; + + if (end > 0 && end <= start) + return; + + strlcpy(path, cpath, sizeof path); +#ifdef _WIN32 + if (strncmp(&path[1], ":\\", 2) == 0) + p = &path[3]; + else +#endif + p = path; + + if (end > 0) + end -= start; + + for (; start > 0; --start) + { + p += strspn(p, PATHSEP); + if (!( p = strchr(p, PATHSEP[0]) )) + return; + } + p += strspn(p, PATHSEP); + for (;;) + { + if (end > 0 && !--end) + break; + + t = p; + if (( p = strchr(p, PATHSEP[0]) )) + { + *p = '\0'; + I_mkdir(path, mode); + *p = PATHSEP[0]; + p += strspn(p, PATHSEP); + } + else + { + if (*t) + I_mkdir(path, mode); + break; + } + } +} + +void M_MkdirEach(const char *path, int start, int mode) +{ + M_MkdirEachUntil(path, start, -1, mode); +} diff --git a/src/m_misc.h b/src/m_misc.h index 99ca8d0c9..e0a73e0b7 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -96,6 +96,11 @@ void M_SetupMemcpy(void); const char *M_FileError(FILE *handle); +int M_PathParts (const char *path); +boolean M_IsPathAbsolute (const char *path); +void M_MkdirEach (const char *path, int start, int mode); +void M_MkdirEachUntil (const char *path, int start, int end, int mode); + // counting bits, for weapon ammo code, usually FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size); diff --git a/src/p_enemy.c b/src/p_enemy.c index 6b6ce62c7..d3c1318cd 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -181,11 +181,9 @@ void A_SpawnObjectAbsolute(mobj_t *actor); void A_SpawnObjectRelative(mobj_t *actor); void A_ChangeAngleRelative(mobj_t *actor); void A_ChangeAngleAbsolute(mobj_t *actor); -#ifdef ROTSPRITE void A_RollAngle(mobj_t *actor); void A_ChangeRollAngleRelative(mobj_t *actor); void A_ChangeRollAngleAbsolute(mobj_t *actor); -#endif // ROTSPRITE void A_PlaySound(mobj_t *actor); void A_FindTarget(mobj_t *actor); void A_FindTracer(mobj_t *actor); @@ -4985,7 +4983,7 @@ void A_ThrownRing(mobj_t *actor) continue; // Don't home in on teammates. - if (gametype == GT_CTF + if ((gametyperules & GTR_TEAMFLAGS) && actor->target->player->ctfteam == player->ctfteam) continue; } @@ -6591,7 +6589,7 @@ void A_OldRingExplode(mobj_t *actor) { if (changecolor) { - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) mo->color = actor->target->color; //copy color else if (actor->target->player->ctfteam == 2) mo->color = skincolor_bluering; @@ -6607,7 +6605,7 @@ void A_OldRingExplode(mobj_t *actor) { if (changecolor) { - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) mo->color = actor->target->color; //copy color else if (actor->target->player->ctfteam == 2) mo->color = skincolor_bluering; @@ -6622,7 +6620,7 @@ void A_OldRingExplode(mobj_t *actor) { if (changecolor) { - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) mo->color = actor->target->color; //copy color else if (actor->target->player->ctfteam == 2) mo->color = skincolor_bluering; @@ -8627,7 +8625,6 @@ void A_ChangeAngleAbsolute(mobj_t *actor) actor->angle = FixedAngle(P_RandomRange(amin, amax)); } -#ifdef ROTSPRITE // Function: A_RollAngle // // Description: Changes the roll angle. @@ -8663,16 +8660,10 @@ void A_RollAngle(mobj_t *actor) // void A_ChangeRollAngleRelative(mobj_t *actor) { - // Oh god, the old code /sucked/. Changed this and the absolute version to get a random range using amin and amax instead of - // getting a random angle from the _entire_ spectrum and then clipping. While we're at it, do the angle conversion to the result - // rather than the ranges, so <0 and >360 work as possible values. -Red INT32 locvar1 = var1; INT32 locvar2 = var2; - //angle_t angle = (P_RandomByte()+1)<<24; const fixed_t amin = locvar1*FRACUNIT; const fixed_t amax = locvar2*FRACUNIT; - //const angle_t amin = FixedAngle(locvar1*FRACUNIT); - //const angle_t amax = FixedAngle(locvar2*FRACUNIT); #ifdef HAVE_BLUA if (LUA_CallAction("A_ChangeRollAngleRelative", actor)) return; @@ -8682,11 +8673,6 @@ void A_ChangeRollAngleRelative(mobj_t *actor) if (amin > amax) I_Error("A_ChangeRollAngleRelative: var1 is greater than var2"); #endif -/* - if (angle < amin) - angle = amin; - if (angle > amax) - angle = amax;*/ actor->rollangle += FixedAngle(P_RandomRange(amin, amax)); } @@ -8702,11 +8688,8 @@ void A_ChangeRollAngleAbsolute(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; - //angle_t angle = (P_RandomByte()+1)<<24; const fixed_t amin = locvar1*FRACUNIT; const fixed_t amax = locvar2*FRACUNIT; - //const angle_t amin = FixedAngle(locvar1*FRACUNIT); - //const angle_t amax = FixedAngle(locvar2*FRACUNIT); #ifdef HAVE_BLUA if (LUA_CallAction("A_ChangeRollAngleAbsolute", actor)) return; @@ -8716,15 +8699,9 @@ void A_ChangeRollAngleAbsolute(mobj_t *actor) if (amin > amax) I_Error("A_ChangeRollAngleAbsolute: var1 is greater than var2"); #endif -/* - if (angle < amin) - angle = amin; - if (angle > amax) - angle = amax;*/ actor->rollangle = FixedAngle(P_RandomRange(amin, amax)); } -#endif // ROTSPRITE // Function: A_PlaySound // diff --git a/src/p_inter.c b/src/p_inter.c index 2645c5e62..e8095ebfc 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -625,7 +625,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_AddPlayerScore(player, 1000); - if (gametype != GT_COOP || modeattacking) // score only? + if (!(gametyperules & GTR_SPECIALSTAGES) || modeattacking) // score only? { S_StartSound(toucher, sfx_chchng); break; @@ -1888,7 +1888,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour char targetname[MAXPLAYERNAME+4]; char sourcename[MAXPLAYERNAME+4]; - if (G_PlatformGametype()) + if (!(gametyperules & (GTR_RINGSLINGER|GTR_HURTMESSAGES))) return; // Not in coop, etc. if (!player) @@ -2093,7 +2093,7 @@ void P_CheckTimeLimit(void) if (!(multiplayer || netgame)) return; - if (G_PlatformGametype()) + if (!(gametyperules & GTR_TIMELIMIT)) return; if (leveltime < timelimitintics) @@ -2124,7 +2124,7 @@ void P_CheckTimeLimit(void) } //Optional tie-breaker for Match/CTF - else if (cv_overtime.value) + else if ((cv_overtime.value) && (gametyperules & GTR_OVERTIME)) { INT32 playerarray[MAXPLAYERS]; INT32 tempplayer = 0; @@ -2206,7 +2206,7 @@ void P_CheckPointLimit(void) if (!(multiplayer || netgame)) return; - if (G_PlatformGametype()) + if (!(gametyperules & GTR_POINTLIMIT)) return; // pointlimit is nonzero, check if it's been reached by this player @@ -2389,7 +2389,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget { if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording! G_StopMetalRecording(true); - if (gametype == GT_MATCH // note, no team match suicide penalty + if ((gametyperules & GTR_DEATHPENALTY) // note, no team match suicide penalty && ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player))) { // Suicide penalty if (target->player->score >= 50) @@ -2962,7 +2962,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget Graue 12-22-2003 */ } -static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) +static void P_NiGHTSDamage(mobj_t *target, mobj_t *source) { player_t *player = target->player; tic_t oldnightstime = player->nightstime; @@ -2978,7 +2978,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) player->flyangle += 180; // Shuffle's BETTERNIGHTSMOVEMENT? player->flyangle %= 360; - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) player->drillmeter -= 5*20; else { @@ -3005,9 +3005,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) P_SetPlayerMobjState(target, S_PLAY_NIGHTS_STUN); S_StartSound(target, sfx_nghurt); -#ifdef ROTSPRITE player->mo->rollangle = 0; -#endif if (oldnightstime > 10*TICRATE && player->nightstime < 10*TICRATE) @@ -3028,7 +3026,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) } } -static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) +static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { player_t *player = target->player; (void)damage; //unused parm @@ -3042,7 +3040,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou return false; // Ignore IT players shooting each other, unless friendlyfire is on. - if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && + if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) && source && source->player && source->player->pflags & PF_TAGIT))) { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) @@ -3058,7 +3056,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou // Don't allow players on the same team to hurt one another, // unless cv_friendlyfire is on. - if (!(cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT)) + if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT)) { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) { @@ -3132,7 +3130,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou return true; } -static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) +static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { player_t *player = target->player; @@ -3143,7 +3141,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj return false; // In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on - if (!cv_friendlyfire.value && (G_PlatformGametype())) + if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && (G_PlatformGametype())) { if (gametype == GT_COOP && inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) // co-op only { @@ -3166,7 +3164,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj { // Don't allow players on the same team to hurt one another, // unless cv_friendlyfire is on. - if (!cv_friendlyfire.value && target->player->ctfteam == source->player->ctfteam) + if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && target->player->ctfteam == source->player->ctfteam) { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) { @@ -3224,7 +3222,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) player->mo->flags2 &= ~MF2_DONTDRAW; P_SetPlayerMobjState(player->mo, player->mo->info->deathstate); - if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) + if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) { P_PlayerFlagBurst(player, false); if (source && source->player) @@ -3349,7 +3347,7 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, else S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss. - if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) + if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) { P_PlayerFlagBurst(player, false); if (source && source->player) @@ -3383,7 +3381,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN P_AddPlayerScore(source->player, 50); } - if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) + if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) { P_PlayerFlagBurst(player, false); if (source && source->player) @@ -3426,6 +3424,24 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) return; + if (!cv_friendlyfire.value) + { + if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) + { + if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. + { + P_SwitchShield(player, SH_PINK); + S_StartSound(player->mo, mobjinfo[MT_PITY_ICON].seesound); + } + } + + if (source->player->ctfteam == player->ctfteam) + return; + } + + if (inflictor->type == MT_LHRT) + return; + if (player->powers[pw_shield] || player->bot) //If One-Hit Shield { P_RemoveShield(player); @@ -3442,7 +3458,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) P_DoPlayerPain(player, inflictor, source); - if (gametype == GT_CTF && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)) + if ((gametyperules & GTR_TEAMFLAGS) && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)) P_PlayerFlagBurst(player, false); if (oldnightstime > 10*TICRATE @@ -3593,7 +3609,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da { if (source == target) return false; // Don't hit yourself with your own paraloop, baka - if (source && source->player && !cv_friendlyfire.value + if (source && source->player && !(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && (gametype == GT_COOP || (G_GametypeHasTeams() && player->ctfteam == source->player->ctfteam))) return false; // Don't run eachother over in special stages and team games and such @@ -3688,7 +3704,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // by friendly fire. Spilling their rings and other items is enough. else if (!force && G_GametypeHasTeams() && source && source->player && (source->player->ctfteam == player->ctfteam) - && cv_friendlyfire.value) + && (cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE))) { damage = 0; P_ShieldDamage(player, inflictor, source, damage, damagetype); diff --git a/src/p_local.h b/src/p_local.h index a5fd0eaa8..a5f95af02 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -115,10 +115,10 @@ typedef struct camera_s extern camera_t camera, camera2; extern consvar_t cv_cam_dist, cv_cam_still, cv_cam_height; -extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed, cv_cam_orbit, cv_cam_adjust; +extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed, cv_cam_turnmultiplier, cv_cam_orbit, cv_cam_adjust; extern consvar_t cv_cam2_dist, cv_cam2_still, cv_cam2_height; -extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed, cv_cam2_orbit, cv_cam2_adjust; +extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed, cv_cam2_turnmultiplier, cv_cam2_orbit, cv_cam2_adjust; extern fixed_t t_cam_dist, t_cam_height, t_cam_rotate; extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate; diff --git a/src/p_map.c b/src/p_map.c index 2d36f747c..1b6f23cde 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -615,7 +615,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) // Why block opposing teams from tailsflying each other? // Sneaking into the hands of a flying tails player in Race might be a viable strategy, who knows. /* - if (gametype == GT_RACE || gametype == GT_COMPETITION + if ((gametyperules & GTR_RACE) || (netgame && (tails->spectator || sonic->spectator)) || (G_TagGametype() && (!(tails->pflags & PF_TAGIT) != !(sonic->pflags & PF_TAGIT))) || (gametype == GT_MATCH) diff --git a/src/p_mobj.c b/src/p_mobj.c index 9b88758c6..cd400f400 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7143,6 +7143,2936 @@ static void P_PyreFlyBurn(mobj_t *mobj, fixed_t hoffs, INT16 vrange, mobjtype_t particle->momz = momz; } +static void P_MobjScaleThink(mobj_t *mobj) +{ + fixed_t oldheight = mobj->height; + UINT8 correctionType = 0; // Don't correct Z position, just gain height + + if ((mobj->flags & MF_NOCLIPHEIGHT || (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz)) + && mobj->type != MT_EGGMOBILE_FIRE) + correctionType = 1; // Correct Z position by centering + else if (mobj->eflags & MFE_VERTICALFLIP) + correctionType = 2; // Correct Z position by moving down + + if (abs(mobj->scale - mobj->destscale) < mobj->scalespeed) + P_SetScale(mobj, mobj->destscale); + else if (mobj->scale < mobj->destscale) + P_SetScale(mobj, mobj->scale + mobj->scalespeed); + else if (mobj->scale > mobj->destscale) + P_SetScale(mobj, mobj->scale - mobj->scalespeed); + + if (correctionType == 1) + mobj->z -= (mobj->height - oldheight)/2; + else if (correctionType == 2) + mobj->z -= mobj->height - oldheight; + + if (mobj->scale == mobj->destscale) + /// \todo Lua hook for "reached destscale"? + switch (mobj->type) + { + case MT_EGGMOBILE_FIRE: + mobj->destscale = FRACUNIT; + mobj->scalespeed = FRACUNIT>>4; + break; + default: + break; + } +} + +static void P_MaceSceneryThink(mobj_t *mobj) +{ + angle_t oldmovedir = mobj->movedir; + + // Always update movedir to prevent desyncing (in the traditional sense, not the netplay sense). + mobj->movedir = (mobj->movedir + mobj->lastlook) & FINEMASK; + + // If too far away and not deliberately spitting in the face of optimisation, don't think! + if (!(mobj->flags2 & MF2_BOSSNOTRAP)) + { + UINT8 i; + // Quick! Look through players! Don't move unless a player is relatively close by. + // The below is selected based on CEZ2's first room. I promise you it is a coincidence that it looks like the weed number. + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(P_AproxDistance(mobj->x - players[i].mo->x, mobj->y - players[i].mo->y), mobj->z - players[i].mo->z) < (4200 << FRACBITS)) + break; // Stop looking. + if (i == MAXPLAYERS) + { + if (!(mobj->flags2 & MF2_BEYONDTHEGRAVE)) + { + mobj_t *ref = mobj; + + // stop/hide all your babies + while ((ref = ref->hnext)) + { + ref->eflags = (((ref->flags & MF_NOTHINK) ? 0 : 1) + | ((ref->flags & MF_NOCLIPTHING) ? 0 : 2) + | ((ref->flags2 & MF2_DONTDRAW) ? 0 : 4)); // oh my god this is nasty. + ref->flags |= MF_NOTHINK|MF_NOCLIPTHING; + ref->flags2 |= MF2_DONTDRAW; + ref->momx = ref->momy = ref->momz = 0; + } + + mobj->flags2 |= MF2_BEYONDTHEGRAVE; + } + return; // don't make bubble! + } + else if (mobj->flags2 & MF2_BEYONDTHEGRAVE) + { + mobj_t *ref = mobj; + + // start/show all your babies + while ((ref = ref->hnext)) + { + if (ref->eflags & 1) + ref->flags &= ~MF_NOTHINK; + if (ref->eflags & 2) + ref->flags &= ~MF_NOCLIPTHING; + if (ref->eflags & 4) + ref->flags2 &= ~MF2_DONTDRAW; + ref->eflags = 0; // le sign + } + + mobj->flags2 &= ~MF2_BEYONDTHEGRAVE; + } + } + + // Okay, time to MOVE + P_MaceRotate(mobj, mobj->movedir, oldmovedir); +} + +static boolean P_DrownNumbersSceneryThink(mobj_t *mobj) +{ + if (!mobj->target) + { + P_RemoveMobj(mobj); + return false; + } + if (!mobj->target->player || !(mobj->target->player->powers[pw_underwater] || mobj->target->player->powers[pw_spacetime])) + { + P_RemoveMobj(mobj); + return false; + } + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + + mobj->destscale = mobj->target->destscale; + P_SetScale(mobj, mobj->target->scale); + + if (mobj->target->eflags & MFE_VERTICALFLIP) + { + mobj->z = mobj->target->z - FixedMul(16*FRACUNIT, mobj->target->scale) - mobj->height; + if (mobj->target->player->pflags & PF_FLIPCAM) + mobj->eflags |= MFE_VERTICALFLIP; + } + else + mobj->z = mobj->target->z + (mobj->target->height) + FixedMul(8*FRACUNIT, mobj->target->scale); // Adjust height for height changes + + if (mobj->threshold <= 35) + mobj->flags2 |= MF2_DONTDRAW; + else + mobj->flags2 &= ~MF2_DONTDRAW; + if (mobj->threshold <= 30) + mobj->threshold = 40; + mobj->threshold--; + return true; +} + +static void P_FlameJetSceneryThink(mobj_t *mobj) +{ + mobj_t *flame; + fixed_t strength; + + if (!(mobj->flags2 & MF2_FIRING)) + return; + + if ((leveltime & 3) == 0) + return; + + // Wave the flames back and forth. Reactiontime determines which direction it's going. + if (mobj->fuse <= -16) + mobj->reactiontime = 1; + else if (mobj->fuse >= 16) + mobj->reactiontime = 0; + + if (mobj->reactiontime) + mobj->fuse += 2; + else + mobj->fuse -= 2; + + flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); + P_SetMobjState(flame, S_FLAMEJETFLAME4); + + flame->angle = mobj->angle; + + if (mobj->flags2 & MF2_AMBUSH) // Wave up and down instead of side-to-side + flame->momz = mobj->fuse << (FRACBITS - 2); + else + flame->angle += FixedAngle(mobj->fuse<movedir; + + P_InstaThrust(flame, flame->angle, strength); + S_StartSound(flame, sfx_fire); +} + +static void P_VerticalFlameJetSceneryThink(mobj_t *mobj) +{ + mobj_t *flame; + fixed_t strength; + + if (!(mobj->flags2 & MF2_FIRING)) + return; + + if ((leveltime & 3) == 0) + return; + + // Wave the flames back and forth. Reactiontime determines which direction it's going. + if (mobj->fuse <= -16) + mobj->reactiontime = 1; + else if (mobj->fuse >= 16) + mobj->reactiontime = 0; + + if (mobj->reactiontime) + mobj->fuse++; + else + mobj->fuse--; + + flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); + + strength = 20*FRACUNIT; + strength -= ((20*FRACUNIT)/16)*mobj->movedir; + + // If deaf'd, the object spawns on the ceiling. + if (mobj->flags2 & MF2_AMBUSH) + { + mobj->z = mobj->ceilingz - mobj->height; + flame->momz = -strength; + } + else + { + flame->momz = strength; + P_SetMobjState(flame, S_FLAMEJETFLAME7); + } + P_InstaThrust(flame, mobj->angle, FixedDiv(mobj->fuse*FRACUNIT, 3*FRACUNIT)); + S_StartSound(flame, sfx_fire); +} + +static boolean P_ParticleGenSceneryThink(mobj_t *mobj) +{ + if (!mobj->lastlook) + return false; + + if (!mobj->threshold) + return false; + + if (--mobj->fuse <= 0) + { + INT32 i = 0; + mobj_t *spawn; + fixed_t bottomheight, topheight; + INT32 type = mobj->threshold, line = mobj->cvmem; + + mobj->fuse = (tic_t)mobj->reactiontime; + + bottomheight = lines[line].frontsector->floorheight; + topheight = lines[line].frontsector->ceilingheight - mobjinfo[(mobjtype_t)type].height; + + if (mobj->waterbottom != bottomheight || mobj->watertop != topheight) + { + if (mobj->movefactor && (topheight > bottomheight)) + mobj->health = (tic_t)(FixedDiv((topheight - bottomheight), abs(mobj->movefactor)) >> FRACBITS); + else + mobj->health = 0; + + mobj->z = ((mobj->flags2 & MF2_OBJECTFLIP) ? topheight : bottomheight); + } + + if (!mobj->health) + return false; + + for (i = 0; i < mobj->lastlook; i++) + { + spawn = P_SpawnMobj( + mobj->x + FixedMul(FixedMul(mobj->friction, mobj->scale), FINECOSINE(mobj->angle >> ANGLETOFINESHIFT)), + mobj->y + FixedMul(FixedMul(mobj->friction, mobj->scale), FINESINE(mobj->angle >> ANGLETOFINESHIFT)), + mobj->z, + (mobjtype_t)mobj->threshold); + P_SetScale(spawn, mobj->scale); + spawn->momz = FixedMul(mobj->movefactor, spawn->scale); + spawn->destscale = spawn->scale/100; + spawn->scalespeed = spawn->scale/mobj->health; + spawn->tics = (tic_t)mobj->health; + spawn->flags2 |= (mobj->flags2 & MF2_OBJECTFLIP); + spawn->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones + + mobj->angle += mobj->movedir; + } + + mobj->angle += (angle_t)mobj->movecount; + } + + return true; +} + +static void P_RosySceneryThink(mobj_t *mobj) +{ + UINT8 i; + fixed_t pdist = 1700*mobj->scale, work, actualwork; + player_t *player = NULL; + statenum_t stat = (mobj->state - states); + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + if (!players[i].mo) + continue; + if (players[i].bot) + continue; + if (!players[i].mo->health) + continue; + actualwork = work = FixedHypot(mobj->x - players[i].mo->x, mobj->y - players[i].mo->y); + if (player) + { + if (players[i].skin == 0 || players[i].skin == 5) + work = (2*work)/3; + if (work >= pdist) + continue; + } + pdist = actualwork; + player = &players[i]; + } + + if (stat == S_ROSY_JUMP || stat == S_ROSY_PAIN) + { + if (P_IsObjectOnGround(mobj)) + { + mobj->momx = mobj->momy = 0; + if (player && mobj->cvmem < (-2*TICRATE)) + stat = S_ROSY_UNHAPPY; + else + stat = S_ROSY_WALK; + P_SetMobjState(mobj, stat); + } + else if (P_MobjFlip(mobj)*mobj->momz < 0) + mobj->frame = mobj->state->frame + mobj->state->var1; + } + + if (!player) + { + if ((stat < S_ROSY_IDLE1 || stat > S_ROSY_IDLE4) && stat != S_ROSY_JUMP) + { + mobj->momx = mobj->momy = 0; + P_SetMobjState(mobj, S_ROSY_IDLE1); + } + } + else + { + boolean dojump = false, targonground, love, makeheart = false; + if (mobj->target != player->mo) + P_SetTarget(&mobj->target, player->mo); + // Tatsuru: Don't try to hug them if they're above or below you! + targonground = (P_IsObjectOnGround(mobj->target) && (player->panim == PA_IDLE || player->panim == PA_WALK || player->panim == PA_RUN) && player->mo->z == mobj->z); + love = (player->skin == 0 || player->skin == 5); + + switch (stat) + { + case S_ROSY_IDLE1: + case S_ROSY_IDLE2: + case S_ROSY_IDLE3: + case S_ROSY_IDLE4: + dojump = true; + break; + case S_ROSY_JUMP: + case S_ROSY_PAIN: + // handled above + break; + case S_ROSY_WALK: + { + fixed_t x = mobj->x, y = mobj->y, z = mobj->z; + angle_t angletoplayer = R_PointToAngle2(x, y, mobj->target->x, mobj->target->y); + boolean allowed = P_TryMove(mobj, mobj->target->x, mobj->target->y, false); + + P_UnsetThingPosition(mobj); + mobj->x = x; + mobj->y = y; + mobj->z = z; + P_SetThingPosition(mobj); + + if (allowed) + { + fixed_t mom, max; + P_Thrust(mobj, angletoplayer, (3*FRACUNIT) >> 1); + mom = FixedHypot(mobj->momx, mobj->momy); + max = pdist; + if ((--mobj->extravalue1) <= 0) + { + if (++mobj->frame > mobj->state->frame + mobj->state->var1) + mobj->frame = mobj->state->frame; + if (mom > 12*mobj->scale) + mobj->extravalue1 = 2; + else if (mom > 6*mobj->scale) + mobj->extravalue1 = 3; + else + mobj->extravalue1 = 4; + } + if (max < (mobj->radius + mobj->target->radius)) + { + mobj->momx = mobj->target->player->cmomx; + mobj->momy = mobj->target->player->cmomy; + if ((mobj->cvmem > TICRATE && !player->exiting) || !targonground) + P_SetMobjState(mobj, (stat = S_ROSY_STND)); + else + { + mobj->target->momx = mobj->momx; + mobj->target->momy = mobj->momy; + P_SetMobjState(mobj, (stat = S_ROSY_HUG)); + S_StartSound(mobj, sfx_cdpcm6); + mobj->angle = angletoplayer; + } + } + else + { + max /= 3; + if (max > 30*mobj->scale) + max = 30*mobj->scale; + if (mom > max && max > mobj->scale) + { + max = FixedDiv(max, mom); + mobj->momx = FixedMul(mobj->momx, max); + mobj->momy = FixedMul(mobj->momy, max); + } + if (abs(mobj->momx) > mobj->scale || abs(mobj->momy) > mobj->scale) + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); + } + } + else + dojump = true; + } + break; + case S_ROSY_HUG: + if (targonground) + { + player->pflags |= PF_STASIS; + if (mobj->cvmem < 5*TICRATE) + mobj->cvmem++; + if (love && !(leveltime & 7)) + makeheart = true; + } + else + { + if (mobj->cvmem < (love ? 5*TICRATE : 0)) + { + P_SetMobjState(mobj, (stat = S_ROSY_PAIN)); + S_StartSound(mobj, sfx_cdpcm7); + } + else + P_SetMobjState(mobj, (stat = S_ROSY_JUMP)); + var1 = var2 = 0; + A_DoNPCPain(mobj); + mobj->cvmem -= TICRATE; + } + break; + case S_ROSY_STND: + if ((pdist > (mobj->radius + mobj->target->radius + 3*(mobj->scale + mobj->target->scale)))) + P_SetMobjState(mobj, (stat = S_ROSY_WALK)); + else if (!targonground) + ; + else + { + if (love && !(leveltime & 15)) + makeheart = true; + if (player->exiting || --mobj->cvmem < TICRATE) + { + P_SetMobjState(mobj, (stat = S_ROSY_HUG)); + S_StartSound(mobj, sfx_cdpcm6); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + mobj->target->momx = mobj->momx; + mobj->target->momy = mobj->momy; + } + } + break; + case S_ROSY_UNHAPPY: + default: + break; + } + + if (stat == S_ROSY_HUG) + { + if (player->panim != PA_IDLE) + P_SetPlayerMobjState(mobj->target, S_PLAY_STND); + player->pflags |= PF_STASIS; + } + + if (dojump) + { + P_SetMobjState(mobj, S_ROSY_JUMP); + mobj->z += P_MobjFlip(mobj); + mobj->momx = mobj->momy = 0; + P_SetObjectMomZ(mobj, 6 << FRACBITS, false); + S_StartSound(mobj, sfx_cdfm02); + } + + if (makeheart) + { + mobj_t *cdlhrt = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_CDLHRT); + cdlhrt->destscale = (5*mobj->scale) >> 4; + P_SetScale(cdlhrt, cdlhrt->destscale); + cdlhrt->fuse = (5*TICRATE) >> 1; + cdlhrt->momz = mobj->scale; + P_SetTarget(&cdlhrt->target, mobj); + cdlhrt->extravalue1 = mobj->x; + cdlhrt->extravalue2 = mobj->y; + } + } +} + +static void P_MobjSceneryThink(mobj_t *mobj) +{ +#ifdef HAVE_BLUA + if (LUAh_MobjThinker(mobj)) + return; + if (P_MobjWasRemoved(mobj)) + return; +#endif + + if ((mobj->flags2 & MF2_SHIELD) && !P_AddShield(mobj)) + return; + + switch (mobj->type) + { + case MT_BOSSJUNK: + mobj->flags2 ^= MF2_DONTDRAW; + break; + case MT_MACEPOINT: + case MT_CHAINMACEPOINT: + case MT_SPRINGBALLPOINT: + case MT_CHAINPOINT: + case MT_FIREBARPOINT: + case MT_CUSTOMMACEPOINT: + case MT_HIDDEN_SLING: + P_MaceSceneryThink(mobj); + break; + case MT_HOOP: + if (mobj->fuse > 1) + P_MoveHoop(mobj); + else if (mobj->fuse == 1) + mobj->movecount = 1; + + if (mobj->movecount) + { + mobj->fuse++; + + if (mobj->fuse > 32) + { + // Don't kill the hoop center. For the sake of respawning. + //if (mobj->target) + // P_RemoveMobj(mobj->target); + + P_RemoveMobj(mobj); + } + } + else + mobj->fuse--; + return; + case MT_NIGHTSPARKLE: + if (mobj->tics != -1) + { + mobj->tics--; + + // you can cycle through multiple states in a tic + if (!mobj->tics) + if (!P_SetMobjState(mobj, mobj->state->nextstate)) + return; // freed itself + } + + P_UnsetThingPosition(mobj); + mobj->x += mobj->momx; + mobj->y += mobj->momy; + mobj->z += mobj->momz; + P_SetThingPosition(mobj); + return; + case MT_NIGHTSLOOPHELPER: + if (--mobj->tics <= 0) + P_RemoveMobj(mobj); + + // Don't touch my fuse! + return; + case MT_OVERLAY: + if (!mobj->target) + { + P_RemoveMobj(mobj); + return; + } + else + P_AddOverlay(mobj); + break; + case MT_PITY_ORB: + case MT_WHIRLWIND_ORB: + case MT_ARMAGEDDON_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + break; + case MT_ATTRACT_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (/*(mobj->target) -- the following is implicit by P_AddShield + && (mobj->target->player) + && */ (mobj->target->player->homing) && (mobj->target->player->pflags & PF_SHIELDABILITY)) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + } + break; + case MT_ELEMENTAL_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL */ + && mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->tracer->state - states) < mobj->info->raisestate + || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + break; + case MT_FORCE_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (/* + && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_FORCE) + && */ (mobj->target->player->pflags & PF_SHIELDABILITY)) + { + mobj_t *whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct + P_SetMobjState(whoosh, mobj->info->raisestate); + whoosh->destscale = whoosh->scale << 1; + whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale); + whoosh->height = 38*whoosh->scale; + whoosh->fuse = 10; + whoosh->flags |= MF_NOCLIPHEIGHT; + whoosh->momz = mobj->target->momz; // Stay reasonably centered for a few frames + mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal whoosh + } + /* FALLTHRU */ + case MT_FLAMEAURA_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if ((statenum_t)(mobj->state - states) < mobj->info->painstate) + mobj->angle = mobj->target->angle; // implicitly okay because of P_AddShield + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_FLAMEAURA */ + && mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->tracer->state - states) < mobj->info->raisestate + || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + break; + case MT_BUBBLEWRAP_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP */ + ) + { + if (mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->state - states) < mobj->info->painstate + || (mobj->state->nextstate < mobj->info->painstate && mobj->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + else if (mobj->target->eflags & MFE_JUSTHITFLOOR + && (statenum_t)(mobj->state - states) == mobj->info->painstate) + { + P_SetMobjState(mobj, mobj->info->painstate + 1); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate + 1); + mobj->tracer->tics++; + } + } + break; + case MT_THUNDERCOIN_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_THUNDERCOIN */ + && (mobj->target->player->pflags & PF_SHIELDABILITY)) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal spark + } + break; + case MT_WATERDROP: + P_SceneryCheckWater(mobj); + if ((mobj->z <= mobj->floorz || mobj->z <= mobj->watertop) + && mobj->health > 0) + { + mobj->health = 0; + P_SetMobjState(mobj, mobj->info->deathstate); + S_StartSound(mobj, mobj->info->deathsound + P_RandomKey(mobj->info->mass)); + return; + } + break; + case MT_BUBBLES: + P_SceneryCheckWater(mobj); + break; + case MT_SMALLBUBBLE: + case MT_MEDIUMBUBBLE: + case MT_EXTRALARGEBUBBLE: // start bubble dissipate + P_SceneryCheckWater(mobj); + if (P_MobjWasRemoved(mobj)) // bubble was removed by not being in water + return; + if (!(mobj->eflags & MFE_UNDERWATER) + || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height >= mobj->ceilingz) + || (mobj->eflags & MFE_VERTICALFLIP && mobj->z <= mobj->floorz) + || (P_CheckDeathPitCollide(mobj)) + || --mobj->fuse <= 0) // Bubbles eventually dissipate if they can't reach the surface. + { + // no playing sound: no point; the object is being removed + P_RemoveMobj(mobj); + return; + } + break; + case MT_LOCKON: + if (!mobj->target) + { + P_RemoveMobj(mobj); + return; + } + + mobj->flags2 &= ~MF2_DONTDRAW; + + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + + mobj->eflags |= (mobj->target->eflags & MFE_VERTICALFLIP); + + mobj->destscale = mobj->target->destscale; + P_SetScale(mobj, mobj->target->scale); + + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z = mobj->target->z + mobj->target->height + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale); + else + mobj->z = mobj->target->z - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale) - mobj->height; + break; + case MT_LOCKONINF: + if (!(mobj->flags2 & MF2_STRONGBOX)) + { + mobj->threshold = mobj->z; + mobj->flags2 |= MF2_STRONGBOX; + } + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z = mobj->threshold + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); + else + mobj->z = mobj->threshold - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); + break; + case MT_DROWNNUMBERS: + if (!P_DrownNumbersSceneryThink(mobj)) + return; + break; + case MT_FLAMEJET: + P_FlameJetSceneryThink(mobj); + break; + case MT_VERTICALFLAMEJET: + P_VerticalFlameJetSceneryThink(mobj); + break; + case MT_FLICKY_01_CENTER: + case MT_FLICKY_02_CENTER: + case MT_FLICKY_03_CENTER: + case MT_FLICKY_04_CENTER: + case MT_FLICKY_05_CENTER: + case MT_FLICKY_06_CENTER: + case MT_FLICKY_07_CENTER: + case MT_FLICKY_08_CENTER: + case MT_FLICKY_09_CENTER: + case MT_FLICKY_10_CENTER: + case MT_FLICKY_11_CENTER: + case MT_FLICKY_12_CENTER: + case MT_FLICKY_13_CENTER: + case MT_FLICKY_14_CENTER: + case MT_FLICKY_15_CENTER: + case MT_FLICKY_16_CENTER: + case MT_SECRETFLICKY_01_CENTER: + case MT_SECRETFLICKY_02_CENTER: + if (mobj->tracer && (mobj->flags & MF_NOCLIPTHING) + && (mobj->flags & MF_GRENADEBOUNCE)) + // for now: only do this bounce routine if flicky is in-place. \todo allow in all movements + { + if (!(mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z <= mobj->tracer->floorz) + mobj->tracer->momz = 7*FRACUNIT; + else if ((mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z >= mobj->tracer->ceilingz - mobj->tracer->height) + mobj->tracer->momz = -7*FRACUNIT; + } + break; + case MT_SEED: + if (P_MobjFlip(mobj)*mobj->momz < mobj->info->speed) + mobj->momz = P_MobjFlip(mobj)*mobj->info->speed; + break; + case MT_ROCKCRUMBLE1: + case MT_ROCKCRUMBLE2: + case MT_ROCKCRUMBLE3: + case MT_ROCKCRUMBLE4: + case MT_ROCKCRUMBLE5: + case MT_ROCKCRUMBLE6: + case MT_ROCKCRUMBLE7: + case MT_ROCKCRUMBLE8: + case MT_ROCKCRUMBLE9: + case MT_ROCKCRUMBLE10: + case MT_ROCKCRUMBLE11: + case MT_ROCKCRUMBLE12: + case MT_ROCKCRUMBLE13: + case MT_ROCKCRUMBLE14: + case MT_ROCKCRUMBLE15: + case MT_ROCKCRUMBLE16: + case MT_WOODDEBRIS: + case MT_BRICKDEBRIS: + case MT_BROKENROBOT: + if (mobj->z <= P_FloorzAtPos(mobj->x, mobj->y, mobj->z, mobj->height) + && mobj->state != &states[mobj->info->deathstate]) + { + P_SetMobjState(mobj, mobj->info->deathstate); + return; + } + break; + case MT_PARTICLEGEN: + if (!P_ParticleGenSceneryThink(mobj)) + return; + break; + case MT_FSGNA: + if (mobj->movedir) + mobj->angle += mobj->movedir; + break; + case MT_ROSY: + P_RosySceneryThink(mobj); + break; + case MT_CDLHRT: + { + if (mobj->cvmem < 24) + mobj->cvmem++; + mobj->movedir += ANG10; + P_UnsetThingPosition(mobj); + mobj->x = mobj->extravalue1 + P_ReturnThrustX(mobj, mobj->movedir, mobj->cvmem*mobj->scale); + mobj->y = mobj->extravalue2 + P_ReturnThrustY(mobj, mobj->movedir, mobj->cvmem*mobj->scale); + P_SetThingPosition(mobj); + if ((--mobj->fuse) < 6) + { + if (!mobj->fuse) + { + P_RemoveMobj(mobj); + return; + } + mobj->frame = (mobj->frame & ~FF_TRANSMASK) | ((10 - (mobj->fuse*2)) << (FF_TRANSSHIFT)); + } + } + break; + case MT_VWREF: + case MT_VWREB: + { + INT32 strength; + ++mobj->movedir; + mobj->frame &= ~FF_TRANSMASK; + strength = min(mobj->fuse, (INT32)mobj->movedir)*3; + if (strength < 10) + mobj->frame |= ((10 - strength) << (FF_TRANSSHIFT)); + } + /* FALLTHRU */ + default: + if (mobj->fuse) + { // Scenery object fuse! Very basic! + mobj->fuse--; + if (!mobj->fuse) + { +#ifdef HAVE_BLUA + if (!LUAh_MobjFuse(mobj)) +#endif + P_RemoveMobj(mobj); + return; + } + } + break; + } + + P_SceneryThinker(mobj); +} + +static boolean P_MobjPushableThink(mobj_t *mobj) +{ + P_MobjCheckWater(mobj); + P_PushableThinker(mobj); + + // Extinguish fire objects in water. (Yes, it's extraordinarily rare to have a pushable flame object, but Brak uses such a case.) + if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL + && (mobj->eflags & (MFE_UNDERWATER | MFE_TOUCHWATER))) + { + P_KillMobj(mobj, NULL, NULL, 0); + return false; + } + + return true; +} + +static boolean P_MobjBossThink(mobj_t *mobj) +{ +#ifdef HAVE_BLUA + if (LUAh_BossThinker(mobj)) + { + if (P_MobjWasRemoved(mobj)) + return false; + } + else if (P_MobjWasRemoved(mobj)) + return false; + else +#endif + switch (mobj->type) + { + case MT_EGGMOBILE: + if (mobj->health < mobj->info->damage + 1 && leveltime & 2) + { + fixed_t rad = mobj->radius >> FRACBITS; + fixed_t hei = mobj->height >> FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(hei / 2, hei) << FRACBITS, + MT_SMOKE); + P_SetObjectMomZ(particle, 2 << FRACBITS, false); + particle->momz += mobj->momz; + } + if (mobj->flags2 & MF2_SKULLFLY) +#if 1 + P_SpawnGhostMobj(mobj); +#else // all the way back from final demo... MT_THOK isn't even the same size anymore! + { + mobj_t *spawnmobj; + spawnmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->painchance); + P_SetTarget(&spawnmobj->target, mobj); + spawnmobj->color = SKINCOLOR_GREY; + } +#endif + P_Boss1Thinker(mobj); + break; + case MT_EGGMOBILE2: + if (mobj->health < mobj->info->damage + 1 && leveltime & 2) + { + fixed_t rad = mobj->radius >> FRACBITS; + fixed_t hei = mobj->height >> FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(hei/2, hei) << FRACBITS, + MT_SMOKE); + P_SetObjectMomZ(particle, 2 << FRACBITS, false); + particle->momz += mobj->momz; + } + P_Boss2Thinker(mobj); + break; + case MT_EGGMOBILE3: + if (mobj->health < mobj->info->damage + 1 && leveltime & 2) + { + fixed_t rad = mobj->radius >> FRACBITS; + fixed_t hei = mobj->height >> FRACBITS; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(hei/2, hei) << FRACBITS, + MT_SMOKE); + P_SetObjectMomZ(particle, 2 << FRACBITS, false); + particle->momz += mobj->momz; + } + P_Boss3Thinker(mobj); + break; + case MT_EGGMOBILE4: + if (mobj->health < mobj->info->damage + 1 && leveltime & 2) + { + fixed_t rad = mobj->radius >> FRACBITS; + fixed_t hei = mobj->height >> FRACBITS; + mobj_t* particle = P_SpawnMobjFromMobj(mobj, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(rad, -rad) << FRACBITS, + P_RandomRange(hei/2, hei) << FRACBITS, + MT_SMOKE); + P_SetObjectMomZ(particle, 2 << FRACBITS, false); + particle->momz += mobj->momz; + } + P_Boss4Thinker(mobj); + break; + case MT_FANG: + P_Boss5Thinker(mobj); + break; + case MT_BLACKEGGMAN: + P_Boss7Thinker(mobj); + break; + case MT_METALSONIC_BATTLE: + P_Boss9Thinker(mobj); + break; + default: // Generic SOC-made boss + if (mobj->flags2 & MF2_SKULLFLY) + P_SpawnGhostMobj(mobj); + P_GenericBossThinker(mobj); + break; + } + if (mobj->flags2 & MF2_BOSSFLEE) + { + if (mobj->extravalue1) + { + if (!(--mobj->extravalue1)) + { + if (mobj->target) + { + mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, P_AproxDistance(mobj->x - mobj->target->x, mobj->y - mobj->target->y)), mobj->scale << 1); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + } + else + mobj->momz = 8*mobj->scale; + } + else + mobj->angle += mobj->movedir; + } + else if (mobj->target) + P_InstaThrust(mobj, mobj->angle, FixedMul(12*FRACUNIT, mobj->scale)); + } + if (mobj->type == MT_CYBRAKDEMON && !mobj->health) + { + if (!(mobj->tics & 1)) + { + var1 = 2; + var2 = 0; + A_BossScream(mobj); + } + if (P_CheckDeathPitCollide(mobj)) + { + P_RemoveMobj(mobj); + return false; + } + if (mobj->momz && mobj->z + mobj->momz <= mobj->floorz) + { + S_StartSound(mobj, sfx_befall); + if (mobj->state != states + S_CYBRAKDEMON_DIE8) + P_SetMobjState(mobj, S_CYBRAKDEMON_DIE8); + } + } + return true; +} + +static boolean P_MobjDeadThink(mobj_t *mobj) +{ + switch (mobj->type) + { + case MT_BLUESPHERE: + if ((mobj->tics >> 2) + 1 > 0 && (mobj->tics >> 2) + 1 <= tr_trans60) // tr_trans50 through tr_trans90, shifting once every second frame + mobj->frame = (NUMTRANSMAPS - ((mobj->tics >> 2) + 1)) << FF_TRANSSHIFT; + else // tr_trans60 otherwise + mobj->frame = tr_trans60 << FF_TRANSSHIFT; + break; + case MT_EGGCAPSULE: + if (mobj->z <= mobj->floorz) + { + P_RemoveMobj(mobj); + return false; + } + break; + case MT_FAKEMOBILE: + if (mobj->scale == mobj->destscale) + { + if (!mobj->fuse) + { + S_StartSound(mobj, sfx_s3k77); + mobj->flags2 |= MF2_DONTDRAW; + mobj->fuse = TICRATE; + } + return false; + } + if (!mobj->reactiontime) + { + if (P_RandomChance(FRACUNIT/2)) + mobj->movefactor = FRACUNIT; + else + mobj->movefactor = -FRACUNIT; + if (P_RandomChance(FRACUNIT/2)) + mobj->movedir = ANG20; + else + mobj->movedir = -ANG20; + mobj->reactiontime = 5; + } + mobj->momz += mobj->movefactor; + mobj->angle += mobj->movedir; + P_InstaThrust(mobj, mobj->angle, -mobj->info->speed); + mobj->reactiontime--; + break; + case MT_EGGSHIELD: + mobj->flags2 ^= MF2_DONTDRAW; + break; + case MT_EGGTRAP: // Egg Capsule animal release + if (mobj->fuse > 0)// && mobj->fuse < TICRATE-(TICRATE/7)) + { + INT32 i; + fixed_t x, y, z; + fixed_t ns; + mobj_t* mo2; + mobj_t* flicky; + + z = mobj->subsector->sector->floorheight + FRACUNIT + (P_RandomKey(64) << FRACBITS); + for (i = 0; i < 3; i++) + { + const angle_t fa = P_RandomKey(FINEANGLES) & FINEMASK; + ns = 64*FRACUNIT; + x = mobj->x + FixedMul(FINESINE(fa), ns); + y = mobj->y + FixedMul(FINECOSINE(fa), ns); + + mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); + P_SetMobjStateNF(mo2, S_XPLD_EGGTRAP); // so the flickies don't lose their target if they spawn + ns = 4*FRACUNIT; + mo2->momx = FixedMul(FINESINE(fa), ns); + mo2->momy = FixedMul(FINECOSINE(fa), ns); + mo2->angle = fa << ANGLETOFINESHIFT; + + if (!i && !(mobj->fuse & 2)) + S_StartSound(mo2, mobj->info->deathsound); + + flicky = P_InternalFlickySpawn(mo2, 0, 8*FRACUNIT, false, -1); + if (!flicky) + break; + + P_SetTarget(&flicky->target, mo2); + flicky->momx = mo2->momx; + flicky->momy = mo2->momy; + } + + mobj->fuse--; + } + break; + case MT_PLAYER: + /// \todo Have the player's dead body completely finish its animation even if they've already respawned. + if (!mobj->fuse) + { // Go away. + /// \todo Actually go ahead and remove mobj completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it. + mobj->momz = 0; + if (mobj->player) + mobj->flags2 |= MF2_DONTDRAW; + else // safe to remove, nobody's going to complain! + { + P_RemoveMobj(mobj); + return false; + } + } + else // Apply gravity to fall downwards. + { + if (mobj->player && !(mobj->fuse % 8) && (mobj->player->charflags & SF_MACHINE)) + { + fixed_t r = mobj->radius >> FRACBITS; + mobj_t *explosion = P_SpawnMobj( + mobj->x + (P_RandomRange(r, -r) << FRACBITS), + mobj->y + (P_RandomRange(r, -r) << FRACBITS), + mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), + MT_SONIC3KBOSSEXPLODE); + S_StartSound(explosion, sfx_s3kb4); + } + if (mobj->movedir == DMG_DROWNED) + P_SetObjectMomZ(mobj, -FRACUNIT/2, true); // slower fall from drowning + else + P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true); + } + break; + case MT_METALSONIC_RACE: + { + if (!(mobj->fuse % 8)) + { + fixed_t r = mobj->radius >> FRACBITS; + mobj_t *explosion = P_SpawnMobj( + mobj->x + (P_RandomRange(r, -r) << FRACBITS), + mobj->y + (P_RandomRange(r, -r) << FRACBITS), + mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), + MT_SONIC3KBOSSEXPLODE); + S_StartSound(explosion, sfx_s3kb4); + } + P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true); + } + break; + default: + break; + } + return true; +} + +// Angle-to-tracer to trigger a linedef exec +// See Linedef Exec 457 (Track mobj angle to point) +static void P_TracerAngleThink(mobj_t *mobj) +{ + angle_t ang; + + if (!mobj->tracer) + return; + + if (!mobj->extravalue2) + return; + + // mobj->lastlook - Don't disable behavior after first failure + // mobj->extravalue1 - Angle tolerance + // mobj->extravalue2 - Exec tag upon failure + // mobj->cvval - Allowable failure delay + // mobj->cvmem - Failure timer + + ang = mobj->angle - R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); + + // \todo account for distance between mobj and tracer + // Because closer mobjs can be facing beyond the angle tolerance + // yet tracer is still in the camera view + + // failure state: mobj is not facing tracer + // Reasaonable defaults: ANGLE_67h, ANGLE_292h + if (ang >= (angle_t)mobj->extravalue1 && ang <= ANGLE_MAX - (angle_t)mobj->extravalue1) + { + if (mobj->cvmem) + mobj->cvmem--; + else + { + INT32 exectag = mobj->extravalue2; // remember this before we erase the values + + if (mobj->lastlook) + mobj->cvmem = mobj->cusval; // reset timer for next failure + else + { + // disable after first failure + mobj->eflags &= ~MFE_TRACERANGLE; + mobj->lastlook = mobj->extravalue1 = mobj->extravalue2 = mobj->cvmem = mobj->cusval = 0; + } + + P_LinedefExecute(exectag, mobj, NULL); + } + } + else + mobj->cvmem = mobj->cusval; // reset failure timer +} + +static void P_ArrowThink(mobj_t *mobj) +{ + if (mobj->flags & MF_MISSILE) + { + // Calculate the angle of movement. + /* + momz + / | + / | + / | + 0------dist(momx,momy) + */ + + fixed_t dist = P_AproxDistance(mobj->momx, mobj->momy); + angle_t angle = R_PointToAngle2(0, 0, dist, mobj->momz); + + if (angle > ANG20 && angle <= ANGLE_180) + mobj->frame = 2; + else if (angle < ANG340 && angle > ANGLE_180) + mobj->frame = 0; + else + mobj->frame = 1; + + if (!(mobj->extravalue1) && (mobj->momz < 0)) + { + mobj->extravalue1 = 1; + S_StartSound(mobj, mobj->info->activesound); + } + if (leveltime & 1) + { + mobj_t *dust = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_PARTICLE); + dust->tics = 18; + dust->scalespeed = 4096; + dust->destscale = FRACUNIT/32; + } + } + else + mobj->flags2 ^= MF2_DONTDRAW; +} + +static void P_BumbleboreThink(mobj_t *mobj) +{ + statenum_t st = mobj->state - states; + if (st == S_BUMBLEBORE_FLY1 || st == S_BUMBLEBORE_FLY2) + { + if (!mobj->target) + P_SetMobjState(mobj, mobj->info->spawnstate); + else if (P_MobjFlip(mobj)*((mobj->z + (mobj->height >> 1)) - (mobj->target->z + (mobj->target->height >> 1))) > 0 + && R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) <= 32*FRACUNIT) + { + mobj->momx >>= 1; + mobj->momy >>= 1; + if (++mobj->movefactor == 4) + { + S_StartSound(mobj, mobj->info->seesound); + mobj->momx = mobj->momy = mobj->momz = 0; + mobj->flags = (mobj->flags|MF_PAIN) & ~MF_NOGRAVITY; + P_SetMobjState(mobj, mobj->info->meleestate); + } + } + else + mobj->movefactor = 0; + } + else if (st == S_BUMBLEBORE_RAISE || st == S_BUMBLEBORE_FALL2) // no _FALL1 because it's an 0-tic + { + if (P_IsObjectOnGround(mobj)) + { + S_StopSound(mobj); + S_StartSound(mobj, mobj->info->attacksound); + mobj->flags = (mobj->flags | MF_NOGRAVITY) & ~MF_PAIN; + mobj->momx = mobj->momy = mobj->momz = 0; + P_SetMobjState(mobj, mobj->info->painstate); + } + else + { + mobj->angle += ANGLE_22h; + mobj->frame = mobj->state->frame + ((mobj->tics & 2) >> 1); + } + } + else if (st == S_BUMBLEBORE_STUCK2 && mobj->tics < TICRATE) + mobj->frame = mobj->state->frame + ((mobj->tics & 2) >> 1); +} + +static boolean P_HangsterThink(mobj_t *mobj) +{ + statenum_t st = mobj->state - states; + //ghost image trail when flying down + if (st == S_HANGSTER_SWOOP1 || st == S_HANGSTER_SWOOP2) + { + P_SpawnGhostMobj(mobj); + //curve when in line with target, otherwise curve to avoid crashing into floor + if ((mobj->z - mobj->floorz <= 80*FRACUNIT) || (mobj->target && (mobj->z - mobj->target->z <= 80*FRACUNIT))) + P_SetMobjState(mobj, (st = S_HANGSTER_ARC1)); + } + + //swoop arc movement stuff + if (st == S_HANGSTER_ARC1) + { + A_FaceTarget(mobj); + P_Thrust(mobj, mobj->angle, 1*FRACUNIT); + } + else if (st == S_HANGSTER_ARC2) + P_Thrust(mobj, mobj->angle, 2*FRACUNIT); + else if (st == S_HANGSTER_ARC3) + P_Thrust(mobj, mobj->angle, 4*FRACUNIT); + //if movement has stopped while flying (like hitting a wall), fly up immediately + else if (st == S_HANGSTER_FLY1 && !mobj->momx && !mobj->momy) + { + mobj->extravalue1 = 0; + P_SetMobjState(mobj, S_HANGSTER_ARCUP1); + } + //after swooping back up, check for ceiling + else if ((st == S_HANGSTER_RETURN1 || st == S_HANGSTER_RETURN2) && mobj->momz == 0 && mobj->ceilingz == (mobj->z + mobj->height)) + P_SetMobjState(mobj, (st = S_HANGSTER_RETURN3)); + + //should you roost on a ceiling with F_SKY1 as its flat, disappear forever + if (st == S_HANGSTER_RETURN3 && mobj->momz == 0 && mobj->ceilingz == (mobj->z + mobj->height) + && mobj->subsector->sector->ceilingpic == skyflatnum + && mobj->subsector->sector->ceilingheight == mobj->ceilingz) + { + P_RemoveMobj(mobj); + return false; + } + + return true; +} + +static boolean P_JetFume1Think(mobj_t *mobj) +{ + fixed_t jetx, jety; + + if (!mobj->target // if you have no target + || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now + { // then remove yourself as well! + P_RemoveMobj(mobj); + return false; + } + + jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); + jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); + + if (mobj->fuse == 56) // First one + { + P_UnsetThingPosition(mobj); + mobj->x = jetx; + mobj->y = jety; + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(38*FRACUNIT, mobj->target->scale); + else + mobj->z = mobj->target->z + FixedMul(38*FRACUNIT, mobj->target->scale); + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + } + else if (mobj->fuse == 57) + { + P_UnsetThingPosition(mobj); + mobj->x = jetx + P_ReturnThrustX(mobj->target, mobj->target->angle - ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); + mobj->y = jety + P_ReturnThrustY(mobj->target, mobj->target->angle - ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(12*FRACUNIT, mobj->target->scale); + else + mobj->z = mobj->target->z + FixedMul(12*FRACUNIT, mobj->target->scale); + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + } + else if (mobj->fuse == 58) + { + P_UnsetThingPosition(mobj); + mobj->x = jetx + P_ReturnThrustX(mobj->target, mobj->target->angle + ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); + mobj->y = jety + P_ReturnThrustY(mobj->target, mobj->target->angle + ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(12*FRACUNIT, mobj->target->scale); + else + mobj->z = mobj->target->z + FixedMul(12*FRACUNIT, mobj->target->scale); + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + } + else if (mobj->fuse == 59) + { + boolean dashmod = ((mobj->target->flags & MF_PAIN) && (mobj->target->health <= mobj->target->info->damage)); + jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, -mobj->target->radius); + jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, -mobj->target->radius); + P_UnsetThingPosition(mobj); + mobj->x = jetx; + mobj->y = jety; + mobj->destscale = mobj->target->scale; + if (!(dashmod && mobj->target->state == states + S_METALSONIC_BOUNCE)) + { + mobj->destscale = (mobj->destscale + FixedDiv(R_PointToDist2(0, 0, mobj->target->momx, mobj->target->momy), 36*mobj->target->scale))/3; + } + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2; + else + mobj->z = mobj->target->z + mobj->target->height/2 - mobj->height/2; + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + if (dashmod) + { + mobj->color = SKINCOLOR_SUNSET; + if (mobj->target->movecount == 3 && !mobj->target->reactiontime && (mobj->target->movedir == 0 || mobj->target->movedir == 2)) + P_SpawnGhostMobj(mobj); + } + else + mobj->color = SKINCOLOR_ICY; + } + mobj->fuse++; + return true; +} + +static boolean P_EggRobo1Think(mobj_t *mobj) +{ +#define SPECTATORRADIUS (96*mobj->scale) + if (!(mobj->flags2 & MF2_STRONGBOX)) + { + mobj->cusval = mobj->x; // eat my SOCs, p_mobj.h warning, we have lua now + mobj->cvmem = mobj->y; // ditto + mobj->movedir = mobj->angle; + mobj->threshold = P_MobjFlip(mobj)*10*mobj->scale; + if (mobj->threshold < 0) + mobj->threshold += (mobj->ceilingz - mobj->height); + else + mobj->threshold += mobj->floorz; + var1 = 4; + A_BossJetFume(mobj); + mobj->flags2 |= MF2_STRONGBOX; + } + + if (mobj->state == &states[mobj->info->deathstate]) // todo: make map actually set health to 0 for these + { + if (mobj->movecount) + { + if (!(--mobj->movecount)) + S_StartSound(mobj, mobj->info->deathsound); + } + else + { + mobj->momz += P_MobjFlip(mobj)*mobj->scale; + if (mobj->momz > 0) + { + if (mobj->z + mobj->momz > mobj->ceilingz + (1000 << FRACBITS)) + { + P_RemoveMobj(mobj); + return false; + } + } + else if (mobj->z + mobj->height + mobj->momz < mobj->floorz - (1000 << FRACBITS)) + { + P_RemoveMobj(mobj); + return false; + } + } + } + else + { + fixed_t basex = mobj->cusval, basey = mobj->cvmem; + + if (mobj->spawnpoint && mobj->spawnpoint->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)) + { + angle_t sideang = mobj->movedir + ((mobj->spawnpoint->options & MTF_AMBUSH) ? ANGLE_90 : -ANGLE_90); + fixed_t oscillate = FixedMul(FINESINE(((leveltime * ANG1) >> (ANGLETOFINESHIFT + 2)) & FINEMASK), 250*mobj->scale); + basex += P_ReturnThrustX(mobj, sideang, oscillate); + basey += P_ReturnThrustY(mobj, sideang, oscillate); + } + + mobj->z = mobj->threshold + FixedMul(FINESINE(((leveltime + mobj->movecount)*ANG2 >> (ANGLETOFINESHIFT - 2)) & FINEMASK), 8*mobj->scale); + if (mobj->state != &states[mobj->info->meleestate]) + { + boolean didmove = false; + + if (mobj->state == &states[mobj->info->spawnstate]) + { + UINT8 i; + fixed_t dist = INT32_MAX; + + for (i = 0; i < MAXPLAYERS; i++) + { + fixed_t compdist; + if (!playeringame[i]) + continue; + if (players[i].spectator) + continue; + if (!players[i].mo) + continue; + if (!players[i].mo->health) + continue; + if (P_PlayerInPain(&players[i])) + continue; + if (players[i].mo->z > mobj->z + mobj->height + 8*mobj->scale) + continue; + if (players[i].mo->z + players[i].mo->height < mobj->z - 8*mobj->scale) + continue; + compdist = P_AproxDistance( + players[i].mo->x + players[i].mo->momx - basex, + players[i].mo->y + players[i].mo->momy - basey); + if (compdist >= dist) + continue; + dist = compdist; + P_SetTarget(&mobj->target, players[i].mo); + } + + if (dist < (SPECTATORRADIUS << 1)) + { + didmove = true; + mobj->frame = 3 + ((leveltime & 2) >> 1); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + + if (P_AproxDistance( + mobj->x - basex, + mobj->y - basey) + < mobj->scale) + S_StartSound(mobj, mobj->info->seesound); + + P_TeleportMove(mobj, + (15*(mobj->x >> 4)) + (basex >> 4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS >> 4), + (15*(mobj->y >> 4)) + (basey >> 4) + P_ReturnThrustY(mobj, mobj->angle, SPECTATORRADIUS >> 4), + mobj->z); + } + else + { + angle_t diff = (mobj->movedir - mobj->angle); + if (diff > ANGLE_180) + diff = InvAngle(InvAngle(diff)/8); + else + diff /= 8; + mobj->angle += diff; + + dist = FINECOSINE(((leveltime + mobj->movecount)*ANG2 >> (ANGLETOFINESHIFT - 2)) & FINEMASK); + + if (abs(dist) < FRACUNIT/2) + mobj->frame = 0; + else + mobj->frame = (dist > 0) ? 1 : 2; + } + } + + if (!didmove) + { + if (P_AproxDistance(mobj->x - basex, mobj->y - basey) < mobj->scale) + P_TeleportMove(mobj, basex, basey, mobj->z); + else + P_TeleportMove(mobj, + (15*(mobj->x >> 4)) + (basex >> 4), + (15*(mobj->y >> 4)) + (basey >> 4), + mobj->z); + } + } + } + return true; +#undef SPECTATORRADIUS +} + +static void P_NiGHTSDroneThink(mobj_t *mobj) +{ + { + // variable setup + mobj_t *goalpost = NULL; + mobj_t *sparkle = NULL; + mobj_t *droneman = NULL; + + boolean flip = mobj->flags2 & MF2_OBJECTFLIP; + boolean topaligned = (mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE); + boolean middlealigned = (mobj->flags & MF_GRENADEBOUNCE) && !(mobj->flags & MF_SLIDEME); + boolean bottomoffsetted = !(mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE); + boolean flipchanged = false; + + fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff; + + if (mobj->target && mobj->target->type == MT_NIGHTSDRONE_GOAL) + { + goalpost = mobj->target; + if (goalpost->target && goalpost->target->type == MT_NIGHTSDRONE_SPARKLING) + sparkle = goalpost->target; + if (goalpost->tracer && goalpost->tracer->type == MT_NIGHTSDRONE_MAN) + droneman = goalpost->tracer; + } + + if (!goalpost || !sparkle || !droneman) + return; + + // did NIGHTSDRONE position, scale, flip, or flags change? all elements need to be synced + droneboxmandiff = max(mobj->height - droneman->height, 0); + dronemangoaldiff = max(droneman->height - goalpost->height, 0); + + if (!(goalpost->flags2 & MF2_OBJECTFLIP) && (mobj->flags2 & MF2_OBJECTFLIP)) + { + goalpost->eflags |= MFE_VERTICALFLIP; + goalpost->flags2 |= MF2_OBJECTFLIP; + sparkle->eflags |= MFE_VERTICALFLIP; + sparkle->flags2 |= MF2_OBJECTFLIP; + droneman->eflags |= MFE_VERTICALFLIP; + droneman->flags2 |= MF2_OBJECTFLIP; + flipchanged = true; + } + else if ((goalpost->flags2 & MF2_OBJECTFLIP) && !(mobj->flags2 & MF2_OBJECTFLIP)) + { + goalpost->eflags &= ~MFE_VERTICALFLIP; + goalpost->flags2 &= ~MF2_OBJECTFLIP; + sparkle->eflags &= ~MFE_VERTICALFLIP; + sparkle->flags2 &= ~MF2_OBJECTFLIP; + droneman->eflags &= ~MFE_VERTICALFLIP; + droneman->flags2 &= ~MF2_OBJECTFLIP; + flipchanged = true; + } + + if (goalpost->destscale != mobj->destscale + || goalpost->movefactor != mobj->z + || goalpost->friction != mobj->height + || flipchanged + || goalpost->threshold != (INT32)(mobj->flags & (MF_SLIDEME|MF_GRENADEBOUNCE))) + { + goalpost->destscale = sparkle->destscale = droneman->destscale = mobj->destscale; + + // straight copy-pasta from P_SpawnMapThing, case MT_NIGHTSDRONE + if (!flip) + { + if (topaligned) // Align droneman to top of hitbox + { + dronemanoffset = droneboxmandiff; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (middlealigned) // Align droneman to center of hitbox + { + dronemanoffset = droneboxmandiff/2; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (bottomoffsetted) + { + dronemanoffset = 24*FRACUNIT; + goaloffset = dronemangoaldiff + dronemanoffset; + } + else + { + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + + sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale); + } + else + { + if (topaligned) // Align droneman to top of hitbox + { + dronemanoffset = 0; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (middlealigned) // Align droneman to center of hitbox + { + dronemanoffset = droneboxmandiff/2; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + else if (bottomoffsetted) + { + dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); + goaloffset = dronemangoaldiff + dronemanoffset; + } + else + { + dronemanoffset = droneboxmandiff; + goaloffset = dronemangoaldiff/2 + dronemanoffset; + } + + sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale); + } + + P_TeleportMove(goalpost, mobj->x, mobj->y, mobj->z + goaloffset); + P_TeleportMove(sparkle, mobj->x, mobj->y, mobj->z + sparkleoffset); + if (goalpost->movefactor != mobj->z || goalpost->friction != mobj->height) + { + P_TeleportMove(droneman, mobj->x, mobj->y, mobj->z + dronemanoffset); + goalpost->movefactor = mobj->z; + goalpost->friction = mobj->height; + } + goalpost->threshold = mobj->flags & (MF_SLIDEME|MF_GRENADEBOUNCE); + } + else + { + if (goalpost->x != mobj->x || goalpost->y != mobj->y) + { + P_TeleportMove(goalpost, mobj->x, mobj->y, goalpost->z); + P_TeleportMove(sparkle, mobj->x, mobj->y, sparkle->z); + } + + if (droneman->x != mobj->x || droneman->y != mobj->y) + P_TeleportMove(droneman, mobj->x, mobj->y, + droneman->z >= mobj->floorz && droneman->z <= mobj->ceilingz ? droneman->z : mobj->z); + } + + // now toggle states! + // GOAL mode? + if (sparkle->state >= &states[S_NIGHTSDRONE_SPARKLING1] && sparkle->state <= &states[S_NIGHTSDRONE_SPARKLING16]) + { + INT32 i; + boolean bonustime = false; + + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) + { + bonustime = true; + break; + } + + if (!bonustime) + { + CONS_Debug(DBG_NIGHTSBASIC, "Removing goal post\n"); + if (goalpost && goalpost->state != &states[S_INVISIBLE]) + P_SetMobjState(goalpost, S_INVISIBLE); + if (sparkle && sparkle->state != &states[S_INVISIBLE]) + P_SetMobjState(sparkle, S_INVISIBLE); + } + } + // Invisible/bouncing mode. + else + { + INT32 i; + boolean bonustime = false; + fixed_t zcomp; + + // Bouncy bouncy! + if (!flip) + { + if (topaligned) + zcomp = droneboxmandiff + mobj->z; + else if (middlealigned) + zcomp = (droneboxmandiff/2) + mobj->z; + else if (bottomoffsetted) + zcomp = mobj->z + FixedMul(24*FRACUNIT, mobj->scale); + else + zcomp = mobj->z; + } + else + { + if (topaligned) + zcomp = mobj->z; + else if (middlealigned) + zcomp = (droneboxmandiff/2) + mobj->z; + else if (bottomoffsetted) + zcomp = mobj->z + droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); + else + zcomp = mobj->z + droneboxmandiff; + } + + droneman->angle += ANG10; + if (!flip && droneman->z <= zcomp) + droneman->momz = FixedMul(5*FRACUNIT, droneman->scale); + else if (flip && droneman->z >= zcomp) + droneman->momz = FixedMul(-5*FRACUNIT, droneman->scale); + + // state switching logic + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) + { + bonustime = true; + break; + } + + if (bonustime) + { + CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n"); + if (!(droneman->flags2 & MF2_DONTDRAW)) + droneman->flags2 |= MF2_DONTDRAW; + if (goalpost->state == &states[S_INVISIBLE]) + P_SetMobjState(goalpost, mobjinfo[goalpost->type].meleestate); + if (sparkle->state == &states[S_INVISIBLE]) + P_SetMobjState(sparkle, mobjinfo[sparkle->type].meleestate); + } + else if (!G_IsSpecialStage(gamemap)) + { + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].powers[pw_carry] != CR_NIGHTSMODE) + { + bonustime = true; // variable reuse + break; + } + + if (bonustime) + { + // show droneman if at least one player is non-nights + if (goalpost->state != &states[S_INVISIBLE]) + P_SetMobjState(goalpost, S_INVISIBLE); + if (sparkle->state != &states[S_INVISIBLE]) + P_SetMobjState(sparkle, S_INVISIBLE); + if (droneman->state != &states[mobjinfo[droneman->type].meleestate]) + P_SetMobjState(droneman, mobjinfo[droneman->type].meleestate); + if (droneman->flags2 & MF2_DONTDRAW) + droneman->flags2 &= ~MF2_DONTDRAW; + } + else + { + // else, hide it + if (!(droneman->flags2 & MF2_DONTDRAW)) + droneman->flags2 |= MF2_DONTDRAW; + } + } + } + } +} + +static boolean P_TurretThink(mobj_t *mobj) +{ + P_MobjCheckWater(mobj); + P_CheckPosition(mobj, mobj->x, mobj->y); + if (P_MobjWasRemoved(mobj)) + return false; + mobj->floorz = tmfloorz; + mobj->ceilingz = tmceilingz; + mobj->floorrover = tmfloorrover; + mobj->ceilingrover = tmceilingrover; + + if ((mobj->eflags & MFE_UNDERWATER) && mobj->health > 0) + { + P_SetMobjState(mobj, mobj->info->deathstate); + mobj->health = 0; + mobj->flags2 &= ~MF2_FIRING; + } + else if (mobj->health > 0 && mobj->z + mobj->height > mobj->ceilingz) // Crushed + { + INT32 i, j; + fixed_t ns; + fixed_t x, y, z; + mobj_t* mo2; + + z = mobj->subsector->sector->floorheight + FixedMul(64*FRACUNIT, mobj->scale); + for (j = 0; j < 2; j++) + { + for (i = 0; i < 32; i++) + { + const angle_t fa = (i*FINEANGLES/16) & FINEMASK; + ns = FixedMul(64*FRACUNIT, mobj->scale); + x = mobj->x + FixedMul(FINESINE(fa), ns); + y = mobj->y + FixedMul(FINECOSINE(fa), ns); + + mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); + ns = FixedMul(16*FRACUNIT, mobj->scale); + mo2->momx = FixedMul(FINESINE(fa), ns); + mo2->momy = FixedMul(FINECOSINE(fa), ns); + } + z -= FixedMul(32*FRACUNIT, mobj->scale); + } + P_SetMobjState(mobj, mobj->info->deathstate); + mobj->health = 0; + mobj->flags2 &= ~MF2_FIRING; + } + return true; +} + +static void P_SaloonDoorThink(mobj_t *mobj) +{ + fixed_t x = mobj->tracer->x; + fixed_t y = mobj->tracer->y; + fixed_t z = mobj->tracer->z; + angle_t oang = FixedAngle(mobj->extravalue1); + angle_t fa = (oang >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t c0 = -96*FINECOSINE(fa); + fixed_t s0 = -96*FINESINE(fa); + angle_t fma; + fixed_t c, s; + angle_t angdiff; + + // Adjust angular speed + fixed_t da = AngleFixed(mobj->angle - oang); + if (da > 180*FRACUNIT) + da -= 360*FRACUNIT; + mobj->extravalue2 = 8*(mobj->extravalue2 - da/32)/9; + + // Update angle + mobj->angle += FixedAngle(mobj->extravalue2); + + angdiff = mobj->angle - FixedAngle(mobj->extravalue1); + if (angdiff > (ANGLE_90 - ANG2) && angdiff < ANGLE_180) + { + mobj->angle = FixedAngle(mobj->extravalue1) + (ANGLE_90 - ANG2); + mobj->extravalue2 /= 2; + } + else if (angdiff < (ANGLE_270 + ANG2) && angdiff >= ANGLE_180) + { + mobj->angle = FixedAngle(mobj->extravalue1) + (ANGLE_270 + ANG2); + mobj->extravalue2 /= 2; + } + + // Update position + fma = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK; + c = 48*FINECOSINE(fma); + s = 48*FINESINE(fma); + P_TeleportMove(mobj, x + c0 + c, y + s0 + s, z); +} + +static void P_PyreFlyThink(mobj_t *mobj) +{ + fixed_t hdist; + + mobj->extravalue1 = (mobj->extravalue1 + 3) % 360; + mobj->z += FINESINE(((mobj->extravalue1 * ANG1) >> ANGLETOFINESHIFT) & FINEMASK); + + if (!(mobj->flags2 & MF2_BOSSNOTRAP)) + P_LookForPlayers(mobj, true, false, 1500*FRACUNIT); + + if (!mobj->target) + return; + + if (mobj->extravalue2 == 1) + P_PyreFlyBurn(mobj, 0, 20, MT_SMOKE, 4*FRACUNIT); + else if (mobj->extravalue2 == 2) + { + INT32 fireradius = min(100 - mobj->fuse, 52); + P_PyreFlyBurn(mobj, P_RandomRange(0, fireradius) << FRACBITS, 20, MT_FLAMEPARTICLE, 4*FRACUNIT); + P_PyreFlyBurn(mobj, fireradius*FRACUNIT, 40, MT_PYREFLY_FIRE, 0); + } + + hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + + if (hdist > 1500*FRACUNIT) + { + mobj->flags2 &= ~MF2_BOSSNOTRAP; + P_SetTarget(&mobj->target, NULL); + return; + } + + if (!(mobj->flags2 & MF2_BOSSNOTRAP) && hdist <= 450*FRACUNIT) + mobj->flags2 |= MF2_BOSSNOTRAP; + + if (!(mobj->flags2 & MF2_BOSSNOTRAP)) + return; + + if (hdist < 1000*FRACUNIT) + { + //Aim for player z position. If too close to floor/ceiling, aim just above/below them. + fixed_t destz = min(max(mobj->target->z, mobj->target->floorz + 70*FRACUNIT), mobj->target->ceilingz - 80*FRACUNIT - mobj->height); + fixed_t dist = P_AproxDistance(hdist, destz - mobj->z); + P_InstaThrust(mobj, R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y), 2*FRACUNIT); + mobj->momz = FixedMul(FixedDiv(destz - mobj->z, dist), 2*FRACUNIT); + } + else + { + mobj->momx = 0; + mobj->momy = 0; + mobj->momz = 0; + } +} + +static void P_PterabyteThink(mobj_t *mobj) +{ + if (mobj->extravalue1 & 4) // Cooldown after grabbing + { + if (mobj->movefactor) + mobj->movefactor--; + else + { + P_SetTarget(&mobj->target, NULL); + mobj->extravalue1 &= 3; + } + } + + if ((mobj->extravalue1 & 3) == 0) // Hovering + { + fixed_t vdist, hdist, time; + fixed_t hspeed = 3*mobj->info->speed; + angle_t fa; + + var1 = 1; + var2 = 0; + A_CapeChase(mobj); + + if (mobj->target) + return; // Still carrying a player or in cooldown + + P_LookForPlayers(mobj, true, false, 256*FRACUNIT); + + if (!mobj->target) + return; + + if (mobj->target->player->powers[pw_flashing]) + { + P_SetTarget(&mobj->target, NULL); + return; + } + + vdist = mobj->z - mobj->target->z - mobj->target->height; + if (P_MobjFlip(mobj)*vdist <= 0) + { + P_SetTarget(&mobj->target, NULL); + return; + } + + hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + if (hdist > 450*FRACUNIT) + { + P_SetTarget(&mobj->target, NULL); + return; + } + + P_SetMobjState(mobj, S_PTERABYTE_SWOOPDOWN); + mobj->extravalue1++; + S_StartSound(mobj, mobj->info->attacksound); + time = FixedDiv(hdist, hspeed); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + fa = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK; + mobj->momx = FixedMul(FINECOSINE(fa), hspeed); + mobj->momy = FixedMul(FINESINE(fa), hspeed); + mobj->momz = -2*FixedDiv(vdist, time); + mobj->extravalue2 = -FixedDiv(mobj->momz, time); //Z accel + mobj->movecount = time >> FRACBITS; + mobj->reactiontime = mobj->movecount; + } + else if ((mobj->extravalue1 & 3) == 1) // Swooping + { + mobj->reactiontime--; + mobj->momz += mobj->extravalue2; + if (mobj->reactiontime) + return; + + if (mobj->state - states == S_PTERABYTE_SWOOPDOWN) + { + P_SetMobjState(mobj, S_PTERABYTE_SWOOPUP); + mobj->reactiontime = mobj->movecount; + } + else if (mobj->state - states == S_PTERABYTE_SWOOPUP) + { + P_SetMobjState(mobj, S_PTERABYTE_FLY1); + mobj->extravalue1++; + if (mobj->target && mobj->target->tracer != mobj) + P_SetTarget(&mobj->target, NULL); // Failed to grab the target + mobj->momx = mobj->momy = mobj->momz = 0; + } + } + else // Returning + { + var1 = 2*mobj->info->speed; + var2 = 1; + A_HomingChase(mobj); + if (P_AproxDistance(mobj->x - mobj->tracer->x, mobj->y - mobj->tracer->y) <= mobj->info->speed) + { + mobj->extravalue1 -= 2; + mobj->momx = mobj->momy = mobj->momz = 0; + } + } +} + +static void P_DragonbomberThink(mobj_t *mobj) +{ +#define DRAGONTURNSPEED ANG2 + mobj->movecount = (mobj->movecount + 9) % 360; + P_SetObjectMomZ(mobj, 4*FINESINE(((mobj->movecount*ANG1) >> ANGLETOFINESHIFT) & FINEMASK), false); + if (mobj->threshold > 0) // are we dropping mines? + { + mobj->threshold--; + if (mobj->threshold == 0) // if the timer hits 0, look for a mine to drop! + { + mobj_t *segment = mobj; + while (segment->tracer != NULL && !P_MobjWasRemoved(segment->tracer) && segment->tracer->state == &states[segment->tracer->info->spawnstate]) + segment = segment->tracer; + if (segment != mobj) // found an unactivated segment? + { + mobj_t *mine = P_SpawnMobjFromMobj(segment, 0, 0, 0, segment->info->painchance); + mine->angle = segment->angle; + P_InstaThrust(mine, mobj->angle, P_AproxDistance(mobj->momx, mobj->momy) >> 1); + P_SetObjectMomZ(mine, -2*FRACUNIT, true); + S_StartSound(mine, mine->info->seesound); + P_SetMobjState(segment, segment->info->raisestate); + mobj->threshold = mobj->info->painchance; + } + } + } + if (mobj->target) // Are we chasing a player? + { + fixed_t dist = P_AproxDistance(mobj->x - mobj->target->x, mobj->y - mobj->target->y); + if (dist > 2000*mobj->scale) // Not anymore! + P_SetTarget(&mobj->target, NULL); + else + { + fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); + fixed_t z = mobj->target->z + (mobj->height >> 1) + (mobj->flags & MFE_VERTICALFLIP ? -128*mobj->scale : 128*mobj->scale + mobj->target->height); + angle_t diff = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) - mobj->angle; + if (diff > ANGLE_180) + mobj->angle -= DRAGONTURNSPEED; + else + mobj->angle += DRAGONTURNSPEED; + if (!mobj->threshold && dist < 512*mobj->scale) // Close enough to drop bombs + { + mobj->threshold = mobj->info->painchance; + } + mobj->momz += max(min(z - mobj->z, vspeed), -vspeed); + } + } + else // Can we find a player to chase? + { + if (mobj->tracer == NULL || mobj->tracer->state != &states[mobj->tracer->info->spawnstate] + || !P_LookForPlayers(mobj, true, false, 2000*mobj->scale)) // if not, circle around the spawnpoint + { + if (!mobj->spawnpoint) // unless we don't have one, in which case uhhh just circle around wherever we currently are I guess?? + mobj->angle += DRAGONTURNSPEED; + else + { + fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); + fixed_t x = mobj->spawnpoint->x << FRACBITS; + fixed_t y = mobj->spawnpoint->y << FRACBITS; + fixed_t z = mobj->spawnpoint->z << FRACBITS; + angle_t diff = R_PointToAngle2(mobj->x, mobj->y, x, y) - mobj->angle; + if (diff > ANGLE_180) + mobj->angle -= DRAGONTURNSPEED; + else + mobj->angle += DRAGONTURNSPEED; + mobj->momz += max(min(z - mobj->z, vspeed), -vspeed); + } + } + } + P_InstaThrust(mobj, mobj->angle, FixedMul(mobj->info->speed, mobj->scale)); +#undef DRAGONTURNSPEED +} + +static boolean P_MobjRegularThink(mobj_t *mobj) +{ + if ((mobj->flags & MF_ENEMY) && (mobj->state->nextstate == mobj->info->spawnstate && mobj->tics == 1)) + mobj->flags2 &= ~MF2_FRET; + + if (mobj->eflags & MFE_TRACERANGLE) + P_TracerAngleThink(mobj); + + switch (mobj->type) + { + case MT_WALLSPIKEBASE: + if (!mobj->target) { + P_RemoveMobj(mobj); + return false; + } + mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|(mobj->target->frame & FF_FRAMEMASK); +#if 0 + if (mobj->angle != mobj->target->angle + ANGLE_90) // reposition if not the correct angle + { + mobj_t* target = mobj->target; // shortcut + const fixed_t baseradius = target->radius - (target->scale/2); //FixedMul(FRACUNIT/2, target->scale); + P_UnsetThingPosition(mobj); + mobj->x = target->x - P_ReturnThrustX(target, target->angle, baseradius); + mobj->y = target->y - P_ReturnThrustY(target, target->angle, baseradius); + P_SetThingPosition(mobj); + mobj->angle = target->angle + ANGLE_90; + } +#endif + break; + case MT_FALLINGROCK: + // Despawn rocks here in case zmovement code can't do so (blame slopes) + if (!mobj->momx && !mobj->momy && !mobj->momz + && ((mobj->eflags & MFE_VERTICALFLIP) ? + mobj->z + mobj->height >= mobj->ceilingz + : mobj->z <= mobj->floorz)) + { + P_RemoveMobj(mobj); + return false; + } + P_MobjCheckWater(mobj); + break; + case MT_ARROW: + P_ArrowThink(mobj); + break; + case MT_EMERALDSPAWN: + if (mobj->threshold) + { + mobj->threshold--; + + if (!mobj->threshold && !mobj->target && mobj->reactiontime) + { + mobj_t *emerald = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->reactiontime); + emerald->threshold = 42; + P_SetTarget(&mobj->target, emerald); + P_SetTarget(&emerald->target, mobj); + } + } + break; + case MT_BUGGLE: + mobj->eflags |= MFE_UNDERWATER; //P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn + { + if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 + && P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z - mobj->z) <= mobj->radius*16) + { + // Home in on the target. + P_HomingAttack(mobj, mobj->tracer); + + if (mobj->z < mobj->floorz) + mobj->z = mobj->floorz; + + if (leveltime % mobj->info->painchance == 0) + S_StartSound(mobj, mobj->info->activesound); + + if ((statenum_t)(mobj->state - states) != mobj->info->seestate) + P_SetMobjState(mobj, mobj->info->seestate); + } + else + { + // Try to find a player + P_LookForPlayers(mobj, true, true, mobj->radius*16); + mobj->momx >>= 1; + mobj->momy >>= 1; + mobj->momz >>= 1; + if ((statenum_t)(mobj->state - states) != mobj->info->spawnstate) + P_SetMobjState(mobj, mobj->info->spawnstate); + } + } + break; + case MT_BUMBLEBORE: + P_BumbleboreThink(mobj); + break; + case MT_BIGMINE: + mobj->extravalue1 += 3; + mobj->extravalue1 %= 360; + P_UnsetThingPosition(mobj); + mobj->z += FINESINE(mobj->extravalue1*(FINEMASK + 1)/360); + P_SetThingPosition(mobj); + break; + case MT_FLAME: + if (mobj->flags2 & MF2_BOSSNOTRAP) + { + if (!mobj->target || P_MobjWasRemoved(mobj->target)) + { + if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) + P_RemoveMobj(mobj->tracer); + P_RemoveMobj(mobj); + return false; + } + mobj->z = mobj->target->z + mobj->target->momz; + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z += mobj->target->height; + } + if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) + { + mobj->tracer->z = mobj->z + P_MobjFlip(mobj)*20*mobj->scale; + if (mobj->eflags & MFE_VERTICALFLIP) + mobj->tracer->z += mobj->height; + } + break; + case MT_WAVINGFLAG1: + case MT_WAVINGFLAG2: + { + fixed_t base = (leveltime << (FRACBITS + 1)); + mobj_t *seg = mobj->tracer, *prev = mobj; + mobj->movedir = mobj->angle + + ((((FINESINE((FixedAngle(base << 1) >> ANGLETOFINESHIFT) & FINEMASK) + + FINESINE((FixedAngle(base << 4) >> ANGLETOFINESHIFT) & FINEMASK)) >> 1) + + FINESINE((FixedAngle(base*9) >> ANGLETOFINESHIFT) & FINEMASK) + + FINECOSINE(((FixedAngle(base*9)) >> ANGLETOFINESHIFT) & FINEMASK)) << 12); //*2^12 + while (seg) + { + seg->movedir = seg->angle; + seg->angle = prev->movedir; + P_UnsetThingPosition(seg); + seg->x = prev->x + P_ReturnThrustX(prev, prev->angle, prev->radius); + seg->y = prev->y + P_ReturnThrustY(prev, prev->angle, prev->radius); + seg->z = prev->z + prev->height - (seg->scale >> 1); + P_SetThingPosition(seg); + prev = seg; + seg = seg->tracer; + } + } + break; + case MT_SPINCUSHION: + if (mobj->target && mobj->state - states >= S_SPINCUSHION_AIM1 && mobj->state - states <= S_SPINCUSHION_AIM5) + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + break; + case MT_CRUSHCLAW: + if (mobj->state - states == S_CRUSHCLAW_STAY && mobj->target) + { + mobj_t *chain = mobj->target->target; + SINT8 sign = ((mobj->tics & 1) ? mobj->tics : -(SINT8)(mobj->tics)); + while (chain) + { + chain->z = chain->watertop + sign*mobj->scale; + sign = -sign; + chain = chain->target; + } + } + break; + case MT_SMASHINGSPIKEBALL: + mobj->momx = mobj->momy = 0; + if (mobj->state - states == S_SMASHSPIKE_FALL && P_IsObjectOnGround(mobj)) + { + P_SetMobjState(mobj, S_SMASHSPIKE_STOMP1); + S_StartSound(mobj, sfx_spsmsh); + } + else if (mobj->state - states == S_SMASHSPIKE_RISE2 && P_MobjFlip(mobj)*(mobj->z - mobj->movecount) >= 0) + { + mobj->momz = 0; + P_SetMobjState(mobj, S_SMASHSPIKE_FLOAT); + } + break; + case MT_HANGSTER: + if (!P_HangsterThink(mobj)) + return false; + break; + case MT_LHRT: + mobj->momx = FixedMul(mobj->momx, mobj->extravalue2); + mobj->momy = FixedMul(mobj->momy, mobj->extravalue2); + break; + case MT_EGGCAPSULE: + if (!mobj->reactiontime) + { + // Target nearest player on your mare. + // (You can make it float up/down by adding MF_FLOAT, + // but beware level design pitfalls.) + fixed_t shortest = 1024*FRACUNIT; + INT32 i; + P_SetTarget(&mobj->target, NULL); + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].mo + && players[i].mare == mobj->threshold && players[i].spheres > 0) + { + fixed_t dist = P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y); + if (dist < shortest) + { + P_SetTarget(&mobj->target, players[i].mo); + shortest = dist; + } + } + } + break; + case MT_EGGMOBILE2_POGO: + if (!mobj->target + || !mobj->target->health + || mobj->target->state == &states[mobj->target->info->spawnstate] + || mobj->target->state == &states[mobj->target->info->raisestate]) + { + P_RemoveMobj(mobj); + return false; + } + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z - mobj->height); + break; + case MT_HAMMER: + if (mobj->z <= mobj->floorz) + { + P_RemoveMobj(mobj); + return false; + } + break; + case MT_KOOPA: + P_KoopaThinker(mobj); + break; + case MT_FIREBALL: + if (P_AproxDistance(mobj->momx, mobj->momy) <= 16*FRACUNIT) // Once fireballs lose enough speed, kill them + { + P_KillMobj(mobj, NULL, NULL, 0); + return false; + } + break; + case MT_REDRING: + if (((mobj->z < mobj->floorz) || (mobj->z + mobj->height > mobj->ceilingz)) + && mobj->flags & MF_MISSILE) + { + P_ExplodeMissile(mobj); + return false; + } + break; + case MT_BOSSFLYPOINT: + return false; + case MT_NIGHTSCORE: + mobj->color = (UINT8)(leveltime % SKINCOLOR_WHITE); + break; + case MT_JETFUME1: + if (!P_JetFume1Think(mobj)) + return false; + break; + case MT_JETFLAME: + { + if (!mobj->target // if you have no target + || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now + { // then remove yourself as well! + P_RemoveMobj(mobj); + return false; + } + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + mobj->z = mobj->target->z - 50*mobj->target->scale; + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + } + break; + case MT_EGGROBO1: + if (!P_EggRobo1Think(mobj)) + return false; + break; + case MT_EGGROBO1JET: + { + if (!mobj->target || P_MobjWasRemoved(mobj->target) // if you have no target + || (mobj->target->health <= 0)) // or your target isn't a boss and it's popped now + { // then remove yourself as well! + P_RemoveMobj(mobj); + return false; + } + + mobj->flags2 ^= MF2_DONTDRAW; + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x + P_ReturnThrustX(mobj, mobj->target->angle + ANGLE_90, mobj->movefactor*mobj->target->scale) - P_ReturnThrustX(mobj, mobj->target->angle, 19*mobj->target->scale); + mobj->y = mobj->target->y + P_ReturnThrustY(mobj, mobj->target->angle + ANGLE_90, mobj->movefactor*mobj->target->scale) - P_ReturnThrustY(mobj, mobj->target->angle, 19*mobj->target->scale); + mobj->z = mobj->target->z; + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->z += (mobj->target->height - mobj->height); + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z + mobj->height; + P_SetThingPosition(mobj); + } + break; + case MT_NIGHTSDRONE: + P_NiGHTSDroneThink(mobj); + break; + case MT_PLAYER: + if (mobj->player) + P_PlayerMobjThinker(mobj); + return false; + case MT_SKIM: + // check mobj against possible water content, before movement code + P_MobjCheckWater(mobj); + + // Keep Skim at water surface + if (mobj->z <= mobj->watertop) + { + mobj->flags |= MF_NOGRAVITY; + if (mobj->z < mobj->watertop) + { + if (mobj->watertop - mobj->z <= FixedMul(mobj->info->speed*FRACUNIT, mobj->scale)) + mobj->z = mobj->watertop; + else + mobj->momz = FixedMul(mobj->info->speed*FRACUNIT, mobj->scale); + } + } + else + { + mobj->flags &= ~MF_NOGRAVITY; + if (mobj->z > mobj->watertop && mobj->z - mobj->watertop < FixedMul(MAXSTEPMOVE, mobj->scale)) + mobj->z = mobj->watertop; + } + break; + case MT_RING: + case MT_REDTEAMRING: + case MT_BLUETEAMRING: + P_KillRingsInLava(mobj); + if (P_MobjWasRemoved(mobj)) + return false; + /* FALLTHRU */ + case MT_COIN: + case MT_BLUESPHERE: + case MT_BOMBSPHERE: + case MT_NIGHTSCHIP: + case MT_NIGHTSSTAR: + // No need to check water. Who cares? + P_RingThinker(mobj); + if (mobj->flags2 & MF2_NIGHTSPULL) + P_NightsItemChase(mobj); + else + A_AttractChase(mobj); + return false; + // Flung items + case MT_FLINGRING: + P_KillRingsInLava(mobj); + if (P_MobjWasRemoved(mobj)) + return false; + /* FALLTHRU */ + case MT_FLINGCOIN: + case MT_FLINGBLUESPHERE: + case MT_FLINGNIGHTSCHIP: + if (mobj->flags2 & MF2_NIGHTSPULL) + P_NightsItemChase(mobj); + else + A_AttractChase(mobj); + break; + case MT_EMBLEM: + if (mobj->flags2 & MF2_NIGHTSPULL) + P_NightsItemChase(mobj); + break; + case MT_SHELL: + if (mobj->threshold && mobj->threshold != TICRATE) + mobj->threshold--; + + if (mobj->threshold >= TICRATE) + { + mobj->angle += ((mobj->movedir == 1) ? ANGLE_22h : ANGLE_337h); + P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), (mobj->info->speed*mobj->scale)); + } + break; + case MT_TURRET: + if (!P_TurretThink(mobj)) + return false; + break; + case MT_BLUEFLAG: + case MT_REDFLAG: + { + sector_t* sec2; + sec2 = P_ThingOnSpecial3DFloor(mobj); + if ((sec2 && GETSECSPECIAL(sec2->special, 4) == 2) || (GETSECSPECIAL(mobj->subsector->sector->special, 4) == 2)) + mobj->fuse = 1; // Return to base. + break; + } + case MT_CANNONBALL: +#ifdef FLOORSPLATS + R_AddFloorSplat(mobj->tracer->subsector, mobj->tracer, "TARGET", mobj->tracer->x, + mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE); +#endif + break; + case MT_SPINDUST: // Spindash dust + mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000 + mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same + //mobj->momz = mobj->momz+P_MobjFlip(mobj)/3; // no meaningful change in value to be frank + if (mobj->state >= &states[S_SPINDUST_BUBBLE1] && mobj->state <= &states[S_SPINDUST_BUBBLE4]) // bubble dust! + { + P_MobjCheckWater(mobj); + if (mobj->watertop != mobj->subsector->sector->floorheight - 1000*FRACUNIT + && mobj->z + mobj->height >= mobj->watertop - 5*FRACUNIT) + mobj->flags2 |= MF2_DONTDRAW; + } + break; + case MT_TRAINDUSTSPAWNER: + if (leveltime % 5 == 0) { + mobj_t* traindust = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PARTICLE); + traindust->flags = MF_SCENERY; + P_SetMobjState(traindust, S_TRAINDUST); + traindust->frame = P_RandomRange(0, 8)|FF_TRANS90; + traindust->angle = mobj->angle; + traindust->tics = TICRATE*4; + traindust->destscale = FRACUNIT*64; + traindust->scalespeed = FRACUNIT/24; + P_SetScale(traindust, FRACUNIT*6); + } + break; + case MT_TRAINSTEAMSPAWNER: + if (leveltime % 5 == 0) { + mobj_t *steam = P_SpawnMobj(mobj->x + FRACUNIT*P_SignedRandom()/2, mobj->y + FRACUNIT*P_SignedRandom()/2, mobj->z, MT_PARTICLE); + P_SetMobjState(steam, S_TRAINSTEAM); + steam->frame = P_RandomRange(0, 1)|FF_TRANS90; + steam->tics = TICRATE*8; + steam->destscale = FRACUNIT*64; + steam->scalespeed = FRACUNIT/8; + P_SetScale(steam, FRACUNIT*16); + steam->momx = P_SignedRandom()*32; + steam->momy = -64*FRACUNIT; + steam->momz = 2*FRACUNIT; + } + break; + case MT_CANARIVORE_GAS: + { + fixed_t momz; + + if (mobj->flags2 & MF2_AMBUSH) + { + mobj->momx = FixedMul(mobj->momx, 50*FRACUNIT/51); + mobj->momy = FixedMul(mobj->momy, 50*FRACUNIT/51); + break; + } + + if (mobj->eflags & MFE_VERTICALFLIP) + { + if ((mobj->z + mobj->height + mobj->momz) <= mobj->ceilingz) + break; + } + else + { + if ((mobj->z + mobj->momz) >= mobj->floorz) + break; + } + + momz = abs(mobj->momz); + if (R_PointToDist2(0, 0, mobj->momx, mobj->momy) < momz) + P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), momz); + mobj->flags2 |= MF2_AMBUSH; + break; + } + case MT_SALOONDOOR: + P_SaloonDoorThink(mobj); + break; + case MT_MINECARTSPAWNER: + P_HandleMinecartSegments(mobj); + if (!mobj->fuse || mobj->fuse > TICRATE) + break; + if (mobj->fuse == 2) + { + mobj->fuse = 0; + break; + } + mobj->flags2 ^= MF2_DONTDRAW; + break; + case MT_LAVAFALLROCK: + if (P_IsObjectOnGround(mobj)) + P_RemoveMobj(mobj); + break; + case MT_PYREFLY: + P_PyreFlyThink(mobj); + break; + case MT_PTERABYTE: + P_PterabyteThink(mobj); + break; + case MT_DRAGONBOMBER: + P_DragonbomberThink(mobj); + break; + case MT_MINUS: + if (P_IsObjectOnGround(mobj)) + mobj->rollangle = 0; + else + mobj->rollangle = R_PointToAngle2(0, 0, mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1)); + break; + case MT_SPINFIRE: + if (mobj->flags & MF_NOGRAVITY) + { + if (mobj->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->ceilingz - mobj->height; + else + mobj->z = mobj->floorz; + } + else if ((!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z <= mobj->floorz) + || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height >= mobj->ceilingz)) + { + mobj->flags |= MF_NOGRAVITY; + mobj->momx = 8; // this is a hack which is used to ensure it still behaves as a missile and can damage others + mobj->momy = mobj->momz = 0; + mobj->z = ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->ceilingz - mobj->height : mobj->floorz); + } + /* FALLTHRU */ + default: + // check mobj against possible water content, before movement code + P_MobjCheckWater(mobj); + + // Extinguish fire objects in water + if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL + && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) + { + P_KillMobj(mobj, NULL, NULL, 0); + return false; + } + break; + } + return true; +} + +static void P_FiringThink(mobj_t *mobj) +{ + if (!mobj->target) + return; + + if (mobj->health <= 0) + return; + + if (mobj->state->action.acp1 == (actionf_p1)A_Boss1Laser) + { + if (mobj->state->tics > 1) + { + var1 = mobj->state->var1; + var2 = mobj->state->var2 & 65535; + mobj->state->action.acp1(mobj); + } + } + else if (leveltime & 1) // Fire mode + { + mobj_t *missile; + + if (mobj->target->player && mobj->target->player->powers[pw_carry] == CR_NIGHTSMODE) + { + fixed_t oldval = mobjinfo[mobj->extravalue1].speed; + + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx, mobj->target->y + mobj->target->momy); + mobjinfo[mobj->extravalue1].speed = FixedMul(60*FRACUNIT, mobj->scale); + missile = P_SpawnMissile(mobj, mobj->target, mobj->extravalue1); + mobjinfo[mobj->extravalue1].speed = oldval; + } + else + { + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + missile = P_SpawnMissile(mobj, mobj->target, mobj->extravalue1); + } + + if (missile) + { + if (mobj->flags2 & MF2_SUPERFIRE) + missile->flags2 |= MF2_SUPERFIRE; + + if (mobj->info->attacksound) + S_StartSound(missile, mobj->info->attacksound); + } + } + else + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); +} + +static void P_MonitorFuseThink(mobj_t *mobj) +{ + mobj_t *newmobj; + + // Special case for ALL monitors. + // If a box's speed is nonzero, it's allowed to respawn as a WRM/SRM. + if (mobj->info->speed != 0 && (mobj->flags2 & (MF2_AMBUSH|MF2_STRONGBOX))) + { + mobjtype_t spawnchance[64]; + INT32 numchoices = 0, i = 0; + + // This define should make it a lot easier to organize and change monitor weights +#define SETMONITORCHANCES(type, strongboxamt, weakboxamt) \ +for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) spawnchance[numchoices++] = type + + // Type SRM WRM + SETMONITORCHANCES(MT_SNEAKERS_BOX, 0, 10); // Super Sneakers + SETMONITORCHANCES(MT_INVULN_BOX, 2, 0); // Invincibility + SETMONITORCHANCES(MT_WHIRLWIND_BOX, 3, 8); // Whirlwind Shield + SETMONITORCHANCES(MT_ELEMENTAL_BOX, 3, 8); // Elemental Shield + SETMONITORCHANCES(MT_ATTRACT_BOX, 2, 0); // Attraction Shield + SETMONITORCHANCES(MT_FORCE_BOX, 3, 3); // Force Shield + SETMONITORCHANCES(MT_ARMAGEDDON_BOX, 2, 0); // Armageddon Shield + SETMONITORCHANCES(MT_MIXUP_BOX, 0, 1); // Teleporters + SETMONITORCHANCES(MT_RECYCLER_BOX, 0, 1); // Recycler + SETMONITORCHANCES(MT_1UP_BOX, 1, 1); // 1-Up + // ======================================= + // Total 16 32 + +#undef SETMONITORCHANCES + + i = P_RandomKey(numchoices); // Gotta love those random numbers! + newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]); + } + else + newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); + + // Transfer flags2 (ambush, strongbox, objectflip) + newmobj->flags2 = mobj->flags2; + P_RemoveMobj(mobj); // make sure they disappear +} + +static void P_FlagFuseThink(mobj_t *mobj) +{ + subsector_t *ss; + fixed_t x, y, z; + mobj_t* flagmo; + + if (!mobj->spawnpoint) + return; + + x = mobj->spawnpoint->x << FRACBITS; + y = mobj->spawnpoint->y << FRACBITS; + ss = R_PointInSubsector(x, y); + if (mobj->spawnpoint->options & MTF_OBJECTFLIP) + { + z = ss->sector->ceilingheight - mobjinfo[mobj->type].height; + if (mobj->spawnpoint->options >> ZSHIFT) + z -= (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; + } + else + { + z = ss->sector->floorheight; + if (mobj->spawnpoint->options >> ZSHIFT) + z += (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; + } + flagmo = P_SpawnMobj(x, y, z, mobj->type); + flagmo->spawnpoint = mobj->spawnpoint; + if (mobj->spawnpoint->options & MTF_OBJECTFLIP) + { + flagmo->eflags |= MFE_VERTICALFLIP; + flagmo->flags2 |= MF2_OBJECTFLIP; + } + + if (mobj->type == MT_REDFLAG) + { + if (!(mobj->flags2 & MF2_JUSTATTACKED)) + CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x85, M_GetText("Red flag"), 0x80); + + // Assumedly in splitscreen players will be on opposing teams + if (players[consoleplayer].ctfteam == 1 || splitscreen) + S_StartSound(NULL, sfx_hoop1); + else if (players[consoleplayer].ctfteam == 2) + S_StartSound(NULL, sfx_hoop3); + + redflag = flagmo; + } + else // MT_BLUEFLAG + { + if (!(mobj->flags2 & MF2_JUSTATTACKED)) + CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x84, M_GetText("Blue flag"), 0x80); + + // Assumedly in splitscreen players will be on opposing teams + if (players[consoleplayer].ctfteam == 2 || splitscreen) + S_StartSound(NULL, sfx_hoop1); + else if (players[consoleplayer].ctfteam == 1) + S_StartSound(NULL, sfx_hoop3); + + blueflag = flagmo; + } +} + +static boolean P_FuseThink(mobj_t *mobj) +{ + if (mobj->type == MT_SNAPPER_HEAD || mobj->type == MT_SNAPPER_LEG || mobj->type == MT_MINECARTSEG) + mobj->flags2 ^= MF2_DONTDRAW; + + mobj->fuse--; + + if (mobj->fuse) + return true; + +#ifdef HAVE_BLUA + if (LUAh_MobjFuse(mobj) || P_MobjWasRemoved(mobj)) + ; + else +#endif + if (mobj->info->flags & MF_MONITOR) + { + P_MonitorFuseThink(mobj); + return false; + } + else switch (mobj->type) + { + // gargoyle and snowman handled in P_PushableThinker, not here + case MT_THROWNGRENADE: + case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: + P_SetMobjState(mobj, mobj->info->deathstate); + break; + case MT_LHRT: + P_KillMobj(mobj, NULL, NULL, 0); + break; + case MT_BLUEFLAG: + case MT_REDFLAG: + P_FlagFuseThink(mobj); + P_RemoveMobj(mobj); + return false; + case MT_FANG: + if (mobj->flags2 & MF2_SLIDEPUSH) + { + var1 = 0; + var2 = 0; + A_BossDeath(mobj); + return false; + } + P_SetMobjState(mobj, mobj->state->nextstate); + if (P_MobjWasRemoved(mobj)) + return false; + break; + case MT_METALSONIC_BATTLE: + break; // don't remove + case MT_SPIKE: + P_SetMobjState(mobj, mobj->state->nextstate); + mobj->fuse = mobj->info->speed; + if (mobj->spawnpoint) + mobj->fuse += mobj->spawnpoint->angle; + break; + case MT_WALLSPIKE: + P_SetMobjState(mobj, mobj->state->nextstate); + mobj->fuse = mobj->info->speed; + if (mobj->spawnpoint) + mobj->fuse += (mobj->spawnpoint->angle / 360); + break; + case MT_NIGHTSCORE: + P_RemoveMobj(mobj); + return false; + case MT_LAVAFALL: + if (mobj->state - states == S_LAVAFALL_DORMANT) + { + mobj->fuse = 30; + P_SetMobjState(mobj, S_LAVAFALL_TELL); + S_StartSound(mobj, mobj->info->seesound); + } + else if (mobj->state - states == S_LAVAFALL_TELL) + { + mobj->fuse = 40; + P_SetMobjState(mobj, S_LAVAFALL_SHOOT); + S_StopSound(mobj); + S_StartSound(mobj, mobj->info->attacksound); + } + else + { + mobj->fuse = 30; + P_SetMobjState(mobj, S_LAVAFALL_DORMANT); + S_StopSound(mobj); + } + return false; + case MT_PYREFLY: + if (mobj->health <= 0) + break; + + mobj->extravalue2 = (mobj->extravalue2 + 1) % 3; + if (mobj->extravalue2 == 0) + { + P_SetMobjState(mobj, mobj->info->spawnstate); + mobj->fuse = 100; + S_StopSound(mobj); + S_StartSound(mobj, sfx_s3k8c); + } + else if (mobj->extravalue2 == 1) + { + mobj->fuse = 50; + S_StartSound(mobj, sfx_s3ka3); + } + else + { + P_SetMobjState(mobj, mobj->info->meleestate); + mobj->fuse = 100; + S_StopSound(mobj); + S_StartSound(mobj, sfx_s3kc2l); + } + return false; + case MT_PLAYER: + break; // don't remove + default: + P_SetMobjState(mobj, mobj->info->xdeathstate); // will remove the mobj if S_NULL. + break; + // Looking for monitors? They moved to a special condition above. + } + + return !P_MobjWasRemoved(mobj); +} + // // P_MobjThinker // @@ -7171,7 +10101,7 @@ void P_MobjThinker(mobj_t *mobj) tmfloorthing = tmhitthing = NULL; - // 970 allows ANY mobj to trigger a linedef exec + // Sector special (2,8) allows ANY mobj to trigger a linedef exec if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8) { sector_t *sec2; @@ -7181,42 +10111,8 @@ void P_MobjThinker(mobj_t *mobj) P_LinedefExecute(sec2->tag, mobj, sec2); } - // Slowly scale up/down to reach your destscale. if (mobj->scale != mobj->destscale) - { - fixed_t oldheight = mobj->height; - UINT8 correctionType = 0; // Don't correct Z position, just gain height - - if ((mobj->flags & MF_NOCLIPHEIGHT || (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz)) - && mobj->type != MT_EGGMOBILE_FIRE) - correctionType = 1; // Correct Z position by centering - else if (mobj->eflags & MFE_VERTICALFLIP) - correctionType = 2; // Correct Z position by moving down - - if (abs(mobj->scale - mobj->destscale) < mobj->scalespeed) - P_SetScale(mobj, mobj->destscale); - else if (mobj->scale < mobj->destscale) - P_SetScale(mobj, mobj->scale + mobj->scalespeed); - else if (mobj->scale > mobj->destscale) - P_SetScale(mobj, mobj->scale - mobj->scalespeed); - - if (correctionType == 1) - mobj->z -= (mobj->height - oldheight)/2; - else if (correctionType == 2) - mobj->z -= mobj->height - oldheight; - - if (mobj->scale == mobj->destscale) - /// \todo Lua hook for "reached destscale"? - switch(mobj->type) - { - case MT_EGGMOBILE_FIRE: - mobj->destscale = FRACUNIT; - mobj->scalespeed = FRACUNIT>>4; - break; - default: - break; - } - } + P_MobjScaleThink(mobj); // Slowly scale up/down to reach your destscale. if ((mobj->type == MT_GHOST || mobj->type == MT_THOK) && mobj->fuse > 0) // Not guaranteed to be MF_SCENERY or not MF_SCENERY! { @@ -7237,806 +10133,7 @@ void P_MobjThinker(mobj_t *mobj) // Special thinker for scenery objects if (mobj->flags & MF_SCENERY) { -#ifdef HAVE_BLUA - if (LUAh_MobjThinker(mobj)) - return; - if (P_MobjWasRemoved(mobj)) - return; -#endif - - if (mobj->flags2 & MF2_SHIELD) - if (!P_AddShield(mobj)) - return; - - switch (mobj->type) - { - case MT_BOSSJUNK: - mobj->flags2 ^= MF2_DONTDRAW; - break; - case MT_MACEPOINT: - case MT_CHAINMACEPOINT: - case MT_SPRINGBALLPOINT: - case MT_CHAINPOINT: - case MT_FIREBARPOINT: - case MT_CUSTOMMACEPOINT: - case MT_HIDDEN_SLING: - { - angle_t oldmovedir = mobj->movedir; - - // Always update movedir to prevent desyncing (in the traditional sense, not the netplay sense). - mobj->movedir = (mobj->movedir + mobj->lastlook) & FINEMASK; - - // If too far away and not deliberately spitting in the face of optimisation, don't think! - if (!(mobj->flags2 & MF2_BOSSNOTRAP)) - { - UINT8 i; - // Quick! Look through players! Don't move unless a player is relatively close by. - // The below is selected based on CEZ2's first room. I promise you it is a coincidence that it looks like the weed number. - for (i = 0; i < MAXPLAYERS; ++i) - if (playeringame[i] && players[i].mo - && P_AproxDistance(P_AproxDistance(mobj->x - players[i].mo->x, mobj->y - players[i].mo->y), mobj->z - players[i].mo->z) < (4200<flags2 & MF2_BEYONDTHEGRAVE)) - { - mobj_t *ref = mobj; - - // stop/hide all your babies - while ((ref = ref->hnext)) - { - ref->eflags = (((ref->flags & MF_NOTHINK) ? 0 : 1) - | ((ref->flags & MF_NOCLIPTHING) ? 0 : 2) - | ((ref->flags2 & MF2_DONTDRAW) ? 0 : 4)); // oh my god this is nasty. - ref->flags |= MF_NOTHINK|MF_NOCLIPTHING; - ref->flags2 |= MF2_DONTDRAW; - ref->momx = ref->momy = ref->momz = 0; - } - - mobj->flags2 |= MF2_BEYONDTHEGRAVE; - } - - break; // don't make bubble! - } - else if (mobj->flags2 & MF2_BEYONDTHEGRAVE) - { - mobj_t *ref = mobj; - - // start/show all your babies - while ((ref = ref->hnext)) - { - if (ref->eflags & 1) - ref->flags &= ~MF_NOTHINK; - if (ref->eflags & 2) - ref->flags &= ~MF_NOCLIPTHING; - if (ref->eflags & 4) - ref->flags2 &= ~MF2_DONTDRAW; - ref->eflags = 0; // le sign - } - - mobj->flags2 &= ~MF2_BEYONDTHEGRAVE; - } - } - - // Okay, time to MOVE - P_MaceRotate(mobj, mobj->movedir, oldmovedir); - } - break; - case MT_HOOP: - if (mobj->fuse > 1) - P_MoveHoop(mobj); - else if (mobj->fuse == 1) - mobj->movecount = 1; - - if (mobj->movecount) - { - mobj->fuse++; - - if (mobj->fuse > 32) - { - // Don't kill the hoop center. For the sake of respawning. - //if (mobj->target) - // P_RemoveMobj(mobj->target); - - P_RemoveMobj(mobj); - } - } - else - mobj->fuse--; - return; - case MT_NIGHTSPARKLE: - if (mobj->tics != -1) - { - mobj->tics--; - - // you can cycle through multiple states in a tic - if (!mobj->tics) - if (!P_SetMobjState(mobj, mobj->state->nextstate)) - return; // freed itself - } - - P_UnsetThingPosition(mobj); - mobj->x += mobj->momx; - mobj->y += mobj->momy; - mobj->z += mobj->momz; - P_SetThingPosition(mobj); - return; - case MT_NIGHTSLOOPHELPER: - if (--mobj->tics <= 0) - P_RemoveMobj(mobj); - - // Don't touch my fuse! - return; - case MT_OVERLAY: - if (!mobj->target) - { - P_RemoveMobj(mobj); - return; - } - else - P_AddOverlay(mobj); - break; - case MT_PITY_ORB: - case MT_WHIRLWIND_ORB: - case MT_ARMAGEDDON_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - break; - case MT_ATTRACT_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if (/*(mobj->target) -- the following is implicit by P_AddShield - && (mobj->target->player) - && */ (mobj->target->player->homing) && (mobj->target->player->pflags & PF_SHIELDABILITY)) - { - P_SetMobjState(mobj, mobj->info->painstate); - mobj->tics++; - } - break; - case MT_ELEMENTAL_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if (mobj->tracer - /* && mobj->target -- the following is implicit by P_AddShield - && mobj->target->player - && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL */ - && mobj->target->player->pflags & PF_SHIELDABILITY - && ((statenum_t)(mobj->tracer->state-states) < mobj->info->raisestate - || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) - { - P_SetMobjState(mobj, mobj->info->painstate); - mobj->tics++; - P_SetMobjState(mobj->tracer, mobj->info->raisestate); - mobj->tracer->tics++; - } - break; - case MT_FORCE_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if (/* - && mobj->target -- the following is implicit by P_AddShield - && mobj->target->player - && (mobj->target->player->powers[pw_shield] & SH_FORCE) - && */ (mobj->target->player->pflags & PF_SHIELDABILITY)) - { - mobj_t *whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct - P_SetMobjState(whoosh, mobj->info->raisestate); - whoosh->destscale = whoosh->scale<<1; - whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale); - whoosh->height = 38*whoosh->scale; - whoosh->fuse = 10; - whoosh->flags |= MF_NOCLIPHEIGHT; - whoosh->momz = mobj->target->momz; // Stay reasonably centered for a few frames - mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal whoosh - } - /* FALLTHRU */ - case MT_FLAMEAURA_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if ((statenum_t)(mobj->state-states) < mobj->info->painstate) - mobj->angle = mobj->target->angle; // implicitly okay because of P_AddShield - if (mobj->tracer - /* && mobj->target -- the following is implicit by P_AddShield - && mobj->target->player - && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_FLAMEAURA */ - && mobj->target->player->pflags & PF_SHIELDABILITY - && ((statenum_t)(mobj->tracer->state-states) < mobj->info->raisestate - || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) - { - P_SetMobjState(mobj, mobj->info->painstate); - mobj->tics++; - P_SetMobjState(mobj->tracer, mobj->info->raisestate); - mobj->tracer->tics++; - } - break; - case MT_BUBBLEWRAP_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if (mobj->tracer - /* && mobj->target -- the following is implicit by P_AddShield - && mobj->target->player - && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP */ - ) - { - if (mobj->target->player->pflags & PF_SHIELDABILITY - && ((statenum_t)(mobj->state-states) < mobj->info->painstate - || (mobj->state->nextstate < mobj->info->painstate && mobj->tics == 1))) - { - P_SetMobjState(mobj, mobj->info->painstate); - mobj->tics++; - P_SetMobjState(mobj->tracer, mobj->info->raisestate); - mobj->tracer->tics++; - } - else if (mobj->target->eflags & MFE_JUSTHITFLOOR - && (statenum_t)(mobj->state-states) == mobj->info->painstate) - { - P_SetMobjState(mobj, mobj->info->painstate+1); - mobj->tics++; - P_SetMobjState(mobj->tracer, mobj->info->raisestate+1); - mobj->tracer->tics++; - } - } - break; - case MT_THUNDERCOIN_ORB: - if (!(mobj->flags2 & MF2_SHIELD)) - return; - if (mobj->tracer - /* && mobj->target -- the following is implicit by P_AddShield - && mobj->target->player - && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_THUNDERCOIN */ - && (mobj->target->player->pflags & PF_SHIELDABILITY)) - { - P_SetMobjState(mobj, mobj->info->painstate); - mobj->tics++; - P_SetMobjState(mobj->tracer, mobj->info->raisestate); - mobj->tracer->tics++; - mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal spark - } - break; - case MT_WATERDROP: - P_SceneryCheckWater(mobj); - if ((mobj->z <= mobj->floorz || mobj->z <= mobj->watertop) - && mobj->health > 0) - { - mobj->health = 0; - P_SetMobjState(mobj, mobj->info->deathstate); - S_StartSound(mobj, mobj->info->deathsound+P_RandomKey(mobj->info->mass)); - return; - } - break; - case MT_BUBBLES: - P_SceneryCheckWater(mobj); - break; - case MT_SMALLBUBBLE: - case MT_MEDIUMBUBBLE: - case MT_EXTRALARGEBUBBLE: // start bubble dissipate - P_SceneryCheckWater(mobj); - if (P_MobjWasRemoved(mobj)) // bubble was removed by not being in water - return; - if (!(mobj->eflags & MFE_UNDERWATER) - || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height >= mobj->ceilingz) - || (mobj->eflags & MFE_VERTICALFLIP && mobj->z <= mobj->floorz) - || (P_CheckDeathPitCollide(mobj)) - || --mobj->fuse <= 0) // Bubbles eventually dissipate if they can't reach the surface. - { - // no playing sound: no point; the object is being removed - P_RemoveMobj(mobj); - return; - } - break; - case MT_LOCKON: - if (!mobj->target) - { - P_RemoveMobj(mobj); - return; - } - - mobj->flags2 &= ~MF2_DONTDRAW; - - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - - mobj->eflags |= (mobj->target->eflags & MFE_VERTICALFLIP); - - mobj->destscale = mobj->target->destscale; - P_SetScale(mobj, mobj->target->scale); - - if (!(mobj->eflags & MFE_VERTICALFLIP)) - mobj->z = mobj->target->z + mobj->target->height + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale); - else - mobj->z = mobj->target->z - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale) - mobj->height; - break; - case MT_LOCKONINF: - if (!(mobj->flags2 & MF2_STRONGBOX)) - { - mobj->threshold = mobj->z; - mobj->flags2 |= MF2_STRONGBOX; - } - if (!(mobj->eflags & MFE_VERTICALFLIP)) - mobj->z = mobj->threshold + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); - else - mobj->z = mobj->threshold - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); - break; - case MT_DROWNNUMBERS: - if (!mobj->target) - { - P_RemoveMobj(mobj); - return; - } - if (!mobj->target->player || !(mobj->target->player->powers[pw_underwater] || mobj->target->player->powers[pw_spacetime])) - { - P_RemoveMobj(mobj); - return; - } - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - - mobj->destscale = mobj->target->destscale; - P_SetScale(mobj, mobj->target->scale); - - if (mobj->target->eflags & MFE_VERTICALFLIP) - { - mobj->z = mobj->target->z - FixedMul(16*FRACUNIT, mobj->target->scale) - mobj->height; - if (mobj->target->player->pflags & PF_FLIPCAM) - mobj->eflags |= MFE_VERTICALFLIP; - } - else - mobj->z = mobj->target->z + (mobj->target->height) + FixedMul(8*FRACUNIT, mobj->target->scale); // Adjust height for height changes - - if (mobj->threshold <= 35) - mobj->flags2 |= MF2_DONTDRAW; - else - mobj->flags2 &= ~MF2_DONTDRAW; - if (mobj->threshold <= 30) - mobj->threshold = 40; - mobj->threshold--; - break; - case MT_FLAMEJET: - if ((mobj->flags2 & MF2_FIRING) && (leveltime & 3) == 0) - { - mobj_t *flame; - fixed_t strength; - - // Wave the flames back and forth. Reactiontime determines which direction it's going. - if (mobj->fuse <= -16) - mobj->reactiontime = 1; - else if (mobj->fuse >= 16) - mobj->reactiontime = 0; - - if (mobj->reactiontime) - mobj->fuse += 2; - else - mobj->fuse -= 2; - - flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); - P_SetMobjState(flame, S_FLAMEJETFLAME4); - - flame->angle = mobj->angle; - - if (mobj->flags2 & MF2_AMBUSH) // Wave up and down instead of side-to-side - flame->momz = mobj->fuse << (FRACBITS-2); - else - flame->angle += FixedAngle(mobj->fuse*FRACUNIT); - - strength = 20*FRACUNIT; - strength -= ((20*FRACUNIT)/16)*mobj->movedir; - - P_InstaThrust(flame, flame->angle, strength); - S_StartSound(flame, sfx_fire); - } - break; - case MT_VERTICALFLAMEJET: - if ((mobj->flags2 & MF2_FIRING) && (leveltime & 3) == 0) - { - mobj_t *flame; - fixed_t strength; - - // Wave the flames back and forth. Reactiontime determines which direction it's going. - if (mobj->fuse <= -16) - mobj->reactiontime = 1; - else if (mobj->fuse >= 16) - mobj->reactiontime = 0; - - if (mobj->reactiontime) - mobj->fuse++; - else - mobj->fuse--; - - flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); - - strength = 20*FRACUNIT; - strength -= ((20*FRACUNIT)/16)*mobj->movedir; - - // If deaf'd, the object spawns on the ceiling. - if (mobj->flags2 & MF2_AMBUSH) - { - mobj->z = mobj->ceilingz-mobj->height; - flame->momz = -strength; - } - else - { - flame->momz = strength; - P_SetMobjState(flame, S_FLAMEJETFLAME7); - } - P_InstaThrust(flame, mobj->angle, FixedDiv(mobj->fuse*FRACUNIT,3*FRACUNIT)); - S_StartSound(flame, sfx_fire); - } - break; - case MT_FLICKY_01_CENTER: - case MT_FLICKY_02_CENTER: - case MT_FLICKY_03_CENTER: - case MT_FLICKY_04_CENTER: - case MT_FLICKY_05_CENTER: - case MT_FLICKY_06_CENTER: - case MT_FLICKY_07_CENTER: - case MT_FLICKY_08_CENTER: - case MT_FLICKY_09_CENTER: - case MT_FLICKY_10_CENTER: - case MT_FLICKY_11_CENTER: - case MT_FLICKY_12_CENTER: - case MT_FLICKY_13_CENTER: - case MT_FLICKY_14_CENTER: - case MT_FLICKY_15_CENTER: - case MT_FLICKY_16_CENTER: - case MT_SECRETFLICKY_01_CENTER: - case MT_SECRETFLICKY_02_CENTER: - if (mobj->tracer && (mobj->flags & MF_NOCLIPTHING) - && (mobj->flags & MF_GRENADEBOUNCE)) - // for now: only do this bounce routine if flicky is in-place. \todo allow in all movements - { - if (!(mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z <= mobj->tracer->floorz) - mobj->tracer->momz = 7*FRACUNIT; - else if ((mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z >= mobj->tracer->ceilingz - mobj->tracer->height) - mobj->tracer->momz = -7*FRACUNIT; - } - break; - case MT_SEED: - if (P_MobjFlip(mobj)*mobj->momz < mobj->info->speed) - mobj->momz = P_MobjFlip(mobj)*mobj->info->speed; - break; - case MT_ROCKCRUMBLE1: - case MT_ROCKCRUMBLE2: - case MT_ROCKCRUMBLE3: - case MT_ROCKCRUMBLE4: - case MT_ROCKCRUMBLE5: - case MT_ROCKCRUMBLE6: - case MT_ROCKCRUMBLE7: - case MT_ROCKCRUMBLE8: - case MT_ROCKCRUMBLE9: - case MT_ROCKCRUMBLE10: - case MT_ROCKCRUMBLE11: - case MT_ROCKCRUMBLE12: - case MT_ROCKCRUMBLE13: - case MT_ROCKCRUMBLE14: - case MT_ROCKCRUMBLE15: - case MT_ROCKCRUMBLE16: - case MT_WOODDEBRIS: - case MT_BRICKDEBRIS: - case MT_BROKENROBOT: - if (mobj->z <= P_FloorzAtPos(mobj->x, mobj->y, mobj->z, mobj->height) - && mobj->state != &states[mobj->info->deathstate]) - { - P_SetMobjState(mobj, mobj->info->deathstate); - return; - } - break; - case MT_PARTICLEGEN: - if (!mobj->lastlook) - return; - - if (!mobj->threshold) - return; - - if (--mobj->fuse <= 0) - { - INT32 i = 0; - mobj_t *spawn; - fixed_t bottomheight, topheight; - INT32 type = mobj->threshold, line = mobj->cvmem; - - mobj->fuse = (tic_t)mobj->reactiontime; - - bottomheight = lines[line].frontsector->floorheight; - topheight = lines[line].frontsector->ceilingheight - mobjinfo[(mobjtype_t)type].height; - - if (mobj->waterbottom != bottomheight || mobj->watertop != topheight) - { - if (mobj->movefactor && (topheight > bottomheight)) - mobj->health = (tic_t)(FixedDiv((topheight - bottomheight), abs(mobj->movefactor)) >> FRACBITS); - else - mobj->health = 0; - - mobj->z = ((mobj->flags2 & MF2_OBJECTFLIP) ? topheight : bottomheight); - } - - if (!mobj->health) - return; - - for (i = 0; i < mobj->lastlook; i++) - { - spawn = P_SpawnMobj( - mobj->x + FixedMul(FixedMul(mobj->friction, mobj->scale), FINECOSINE(mobj->angle>>ANGLETOFINESHIFT)), - mobj->y + FixedMul(FixedMul(mobj->friction, mobj->scale), FINESINE(mobj->angle>>ANGLETOFINESHIFT)), - mobj->z, - (mobjtype_t)mobj->threshold); - P_SetScale(spawn, mobj->scale); - spawn->momz = FixedMul(mobj->movefactor, spawn->scale); - spawn->destscale = spawn->scale/100; - spawn->scalespeed = spawn->scale/mobj->health; - spawn->tics = (tic_t)mobj->health; - spawn->flags2 |= (mobj->flags2 & MF2_OBJECTFLIP); - spawn->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones - - mobj->angle += mobj->movedir; - } - - mobj->angle += (angle_t)mobj->movecount; - } - break; - case MT_FSGNA: - if (mobj->movedir) - mobj->angle += mobj->movedir; - break; - case MT_ROSY: - { - UINT8 i; - fixed_t pdist = 1700*mobj->scale, work, actualwork; - player_t *player = NULL; - statenum_t stat = (mobj->state-states); - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - if (!players[i].mo) - continue; - if (players[i].bot) - continue; - if (!players[i].mo->health) - continue; - actualwork = work = FixedHypot(mobj->x-players[i].mo->x, mobj->y-players[i].mo->y); - if (player) - { - if (players[i].skin == 0 || players[i].skin == 5) - work = (2*work)/3; - if (work >= pdist) - continue; - } - pdist = actualwork; - player = &players[i]; - } - - if (stat == S_ROSY_JUMP || stat == S_ROSY_PAIN) - { - if (P_IsObjectOnGround(mobj)) - { - mobj->momx = mobj->momy = 0; - if (player && mobj->cvmem < (-2*TICRATE)) - stat = S_ROSY_UNHAPPY; - else - stat = S_ROSY_WALK; - P_SetMobjState(mobj, stat); - } - else if (P_MobjFlip(mobj)*mobj->momz < 0) - mobj->frame = mobj->state->frame+mobj->state->var1; - } - - if (!player) - { - if ((stat < S_ROSY_IDLE1 || stat > S_ROSY_IDLE4) && stat != S_ROSY_JUMP) - { - mobj->momx = mobj->momy = 0; - P_SetMobjState(mobj, S_ROSY_IDLE1); - } - } - else - { - boolean dojump = false, targonground, love, makeheart = false; - if (mobj->target != player->mo) - P_SetTarget(&mobj->target, player->mo); - // Tatsuru: Don't try to hug them if they're above or below you! - targonground = (P_IsObjectOnGround(mobj->target) && (player->panim == PA_IDLE || player->panim == PA_WALK || player->panim == PA_RUN) && player->mo->z == mobj->z); - love = (player->skin == 0 || player->skin == 5); - - switch (stat) - { - case S_ROSY_IDLE1: - case S_ROSY_IDLE2: - case S_ROSY_IDLE3: - case S_ROSY_IDLE4: - dojump = true; - break; - case S_ROSY_JUMP: - case S_ROSY_PAIN: - // handled above - break; - case S_ROSY_WALK: - { - fixed_t x = mobj->x, y = mobj->y, z = mobj->z; - angle_t angletoplayer = R_PointToAngle2(x, y, mobj->target->x, mobj->target->y); - boolean allowed = P_TryMove(mobj, mobj->target->x, mobj->target->y, false); - - P_UnsetThingPosition(mobj); - mobj->x = x; - mobj->y = y; - mobj->z = z; - P_SetThingPosition(mobj); - - if (allowed) - { - fixed_t mom, max; - P_Thrust(mobj, angletoplayer, (3*FRACUNIT)>>1); - mom = FixedHypot(mobj->momx, mobj->momy); - max = pdist; - if ((--mobj->extravalue1) <= 0) - { - if (++mobj->frame > mobj->state->frame+mobj->state->var1) - mobj->frame = mobj->state->frame; - if (mom > 12*mobj->scale) - mobj->extravalue1 = 2; - else if (mom > 6*mobj->scale) - mobj->extravalue1 = 3; - else - mobj->extravalue1 = 4; - } - if (max < (mobj->radius + mobj->target->radius)) - { - mobj->momx = mobj->target->player->cmomx; - mobj->momy = mobj->target->player->cmomy; - if ((mobj->cvmem > TICRATE && !player->exiting) || !targonground) - P_SetMobjState(mobj, (stat = S_ROSY_STND)); - else - { - mobj->target->momx = mobj->momx; - mobj->target->momy = mobj->momy; - P_SetMobjState(mobj, (stat = S_ROSY_HUG)); - S_StartSound(mobj, sfx_cdpcm6); - mobj->angle = angletoplayer; - } - } - else - { - max /= 3; - if (max > 30*mobj->scale) - max = 30*mobj->scale; - if (mom > max && max > mobj->scale) - { - max = FixedDiv(max, mom); - mobj->momx = FixedMul(mobj->momx, max); - mobj->momy = FixedMul(mobj->momy, max); - } - if (abs(mobj->momx) > mobj->scale || abs(mobj->momy) > mobj->scale) - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - } - } - else - dojump = true; - } - break; - case S_ROSY_HUG: - if (targonground) - { - player->pflags |= PF_STASIS; - if (mobj->cvmem < 5*TICRATE) - mobj->cvmem++; - if (love && !(leveltime & 7)) - makeheart = true; - } - else - { - if (mobj->cvmem < (love ? 5*TICRATE : 0)) - { - P_SetMobjState(mobj, (stat = S_ROSY_PAIN)); - S_StartSound(mobj, sfx_cdpcm7); - } - else - P_SetMobjState(mobj, (stat = S_ROSY_JUMP)); - var1 = var2 = 0; - A_DoNPCPain(mobj); - mobj->cvmem -= TICRATE; - } - break; - case S_ROSY_STND: - if ((pdist > (mobj->radius + mobj->target->radius + 3*(mobj->scale + mobj->target->scale)))) - P_SetMobjState(mobj, (stat = S_ROSY_WALK)); - else if (!targonground) - ; - else - { - if (love && !(leveltime & 15)) - makeheart = true; - if (player->exiting || --mobj->cvmem < TICRATE) - { - P_SetMobjState(mobj, (stat = S_ROSY_HUG)); - S_StartSound(mobj, sfx_cdpcm6); - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - mobj->target->momx = mobj->momx; - mobj->target->momy = mobj->momy; - } - } - break; - case S_ROSY_UNHAPPY: - default: - break; - } - - if (stat == S_ROSY_HUG) - { - if (player->panim != PA_IDLE) - P_SetPlayerMobjState(mobj->target, S_PLAY_STND); - player->pflags |= PF_STASIS; - } - - if (dojump) - { - P_SetMobjState(mobj, S_ROSY_JUMP); - mobj->z += P_MobjFlip(mobj); - mobj->momx = mobj->momy = 0; - P_SetObjectMomZ(mobj, 6<height, MT_CDLHRT); - cdlhrt->destscale = (5*mobj->scale)>>4; - P_SetScale(cdlhrt, cdlhrt->destscale); - cdlhrt->fuse = (5*TICRATE)>>1; - cdlhrt->momz = mobj->scale; - P_SetTarget(&cdlhrt->target, mobj); - cdlhrt->extravalue1 = mobj->x; - cdlhrt->extravalue2 = mobj->y; - } - } - } - break; - case MT_CDLHRT: - { - if (mobj->cvmem < 24) - mobj->cvmem++; - mobj->movedir += ANG10; - P_UnsetThingPosition(mobj); - mobj->x = mobj->extravalue1 + P_ReturnThrustX(mobj, mobj->movedir, mobj->cvmem*mobj->scale); - mobj->y = mobj->extravalue2 + P_ReturnThrustY(mobj, mobj->movedir, mobj->cvmem*mobj->scale); - P_SetThingPosition(mobj); - if ((--mobj->fuse) < 6) - { - if (!mobj->fuse) - { - P_RemoveMobj(mobj); - return; - } - mobj->frame = (mobj->frame & ~FF_TRANSMASK)|((10-(mobj->fuse*2))<<(FF_TRANSSHIFT)); - } - } - break; - case MT_VWREF: - case MT_VWREB: - { - INT32 strength; - ++mobj->movedir; - mobj->frame &= ~FF_TRANSMASK; - strength = min(mobj->fuse, (INT32)mobj->movedir)*3; - if (strength < 10) - mobj->frame |= ((10-strength)<<(FF_TRANSSHIFT)); - } - /* FALLTHRU */ - default: - if (mobj->fuse) - { // Scenery object fuse! Very basic! - mobj->fuse--; - if (!mobj->fuse) - { -#ifdef HAVE_BLUA - if (!LUAh_MobjFuse(mobj)) -#endif - P_RemoveMobj(mobj); - return; - } - } - break; - } - - P_SceneryThinker(mobj); + P_MobjSceneryThink(mobj); return; } @@ -8059,1768 +10156,29 @@ void P_MobjThinker(mobj_t *mobj) // separate thinker if (mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse)) { - P_MobjCheckWater(mobj); - P_PushableThinker(mobj); - - // Extinguish fire objects in water. (Yes, it's extraordinarily rare to have a pushable flame object, but Brak uses such a case.) - if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL - && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) - { - P_KillMobj(mobj, NULL, NULL, 0); + if (!P_MobjPushableThink(mobj)) return; - } } else if (mobj->flags & MF_BOSS) { -#ifdef HAVE_BLUA - if (LUAh_BossThinker(mobj)) - { - if (P_MobjWasRemoved(mobj)) - return; - } - else if (P_MobjWasRemoved(mobj)) + if (!P_MobjBossThink(mobj)) return; - else -#endif - switch (mobj->type) - { - case MT_EGGMOBILE: - if (mobj->health < mobj->info->damage+1 && leveltime & 2) - { - fixed_t rad = mobj->radius>>FRACBITS; - fixed_t hei = mobj->height>>FRACBITS; - mobj_t *particle = P_SpawnMobjFromMobj(mobj, - P_RandomRange(rad, -rad)<momz += mobj->momz; - } - if (mobj->flags2 & MF2_SKULLFLY) -#if 1 - P_SpawnGhostMobj(mobj); -#else // all the way back from final demo... MT_THOK isn't even the same size anymore! - { - mobj_t *spawnmobj; - spawnmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->painchance); - P_SetTarget(&spawnmobj->target, mobj); - spawnmobj->color = SKINCOLOR_GREY; - } -#endif - P_Boss1Thinker(mobj); - break; - case MT_EGGMOBILE2: - if (mobj->health < mobj->info->damage+1 && leveltime & 2) - { - fixed_t rad = mobj->radius>>FRACBITS; - fixed_t hei = mobj->height>>FRACBITS; - mobj_t *particle = P_SpawnMobjFromMobj(mobj, - P_RandomRange(rad, -rad)<momz += mobj->momz; - } - P_Boss2Thinker(mobj); - break; - case MT_EGGMOBILE3: - if (mobj->health < mobj->info->damage+1 && leveltime & 2) - { - fixed_t rad = mobj->radius>>FRACBITS; - fixed_t hei = mobj->height>>FRACBITS; - mobj_t *particle = P_SpawnMobjFromMobj(mobj, - P_RandomRange(rad, -rad)<momz += mobj->momz; - } - P_Boss3Thinker(mobj); - break; - case MT_EGGMOBILE4: - if (mobj->health < mobj->info->damage+1 && leveltime & 2) - { - fixed_t rad = mobj->radius>>FRACBITS; - fixed_t hei = mobj->height>>FRACBITS; - mobj_t *particle = P_SpawnMobjFromMobj(mobj, - P_RandomRange(rad, -rad)<momz += mobj->momz; - } - P_Boss4Thinker(mobj); - break; - case MT_FANG: - P_Boss5Thinker(mobj); - break; - case MT_BLACKEGGMAN: - P_Boss7Thinker(mobj); - break; - case MT_METALSONIC_BATTLE: - P_Boss9Thinker(mobj); - break; - default: // Generic SOC-made boss - if (mobj->flags2 & MF2_SKULLFLY) - P_SpawnGhostMobj(mobj); - P_GenericBossThinker(mobj); - break; - } - if (mobj->flags2 & MF2_BOSSFLEE) - { - if (mobj->extravalue1) - { - if (!(--mobj->extravalue1)) - { - if (mobj->target) - { - mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, P_AproxDistance(mobj->x-mobj->target->x,mobj->y-mobj->target->y)), mobj->scale<<1); - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - } - else - mobj->momz = 8*mobj->scale; - } - else - mobj->angle += mobj->movedir; - } - else if (mobj->target) - P_InstaThrust(mobj, mobj->angle, FixedMul(12*FRACUNIT, mobj->scale)); - } - if (mobj->type == MT_CYBRAKDEMON && !mobj->health) - { - if (!(mobj->tics & 1)) - { - var1 = 2; - var2 = 0; - A_BossScream(mobj); - } - if (P_CheckDeathPitCollide(mobj)) - { - P_RemoveMobj(mobj); - return; - } - if (mobj->momz && mobj->z+mobj->momz <= mobj->floorz) - { - S_StartSound(mobj, sfx_befall); - if (mobj->state != states+S_CYBRAKDEMON_DIE8) - P_SetMobjState(mobj, S_CYBRAKDEMON_DIE8); - } - } } else if (mobj->health <= 0) // Dead things think differently than the living. - switch (mobj->type) - { - case MT_BLUESPHERE: - if ((mobj->tics>>2)+1 > 0 && (mobj->tics>>2)+1 <= tr_trans60) // tr_trans50 through tr_trans90, shifting once every second frame - mobj->frame = (NUMTRANSMAPS-((mobj->tics>>2)+1))<frame = tr_trans60<z <= mobj->floorz) - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_FAKEMOBILE: - if (mobj->scale == mobj->destscale) - { - if (!mobj->fuse) - { - S_StartSound(mobj, sfx_s3k77); - mobj->flags2 |= MF2_DONTDRAW; - mobj->fuse = TICRATE; - } - return; - } - if (!mobj->reactiontime) - { - if (P_RandomChance(FRACUNIT/2)) - mobj->movefactor = FRACUNIT; - else - mobj->movefactor = -FRACUNIT; - if (P_RandomChance(FRACUNIT/2)) - mobj->movedir = ANG20; - else - mobj->movedir = -ANG20; - mobj->reactiontime = 5; - } - mobj->momz += mobj->movefactor; - mobj->angle += mobj->movedir; - P_InstaThrust(mobj, mobj->angle, -mobj->info->speed); - mobj->reactiontime--; - break; - case MT_EGGSHIELD: - mobj->flags2 ^= MF2_DONTDRAW; - break; - case MT_EGGTRAP: // Egg Capsule animal release - if (mobj->fuse > 0)// && mobj->fuse < TICRATE-(TICRATE/7)) - { - INT32 i; - fixed_t x,y,z; - fixed_t ns; - mobj_t *mo2; - mobj_t *flicky; - - z = mobj->subsector->sector->floorheight + FRACUNIT + (P_RandomKey(64)<x + FixedMul(FINESINE(fa),ns); - y = mobj->y + FixedMul(FINECOSINE(fa),ns); - - mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); - P_SetMobjStateNF(mo2, S_XPLD_EGGTRAP); // so the flickies don't lose their target if they spawn - ns = 4 * FRACUNIT; - mo2->momx = FixedMul(FINESINE(fa),ns); - mo2->momy = FixedMul(FINECOSINE(fa),ns); - mo2->angle = fa << ANGLETOFINESHIFT; - - if (!i && !(mobj->fuse & 2)) - S_StartSound(mo2, mobj->info->deathsound); - - flicky = P_InternalFlickySpawn(mo2, 0, 8*FRACUNIT, false, -1); - if (!flicky) - break; - - P_SetTarget(&flicky->target, mo2); - flicky->momx = mo2->momx; - flicky->momy = mo2->momy; - } - - mobj->fuse--; - } - break; - case MT_PLAYER: - /// \todo Have the player's dead body completely finish its animation even if they've already respawned. - if (!mobj->fuse) - { // Go away. - /// \todo Actually go ahead and remove mobj completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it. - mobj->momz = 0; - if (mobj->player) - mobj->flags2 |= MF2_DONTDRAW; - else // safe to remove, nobody's going to complain! - { - P_RemoveMobj(mobj); - return; - } - } - else // Apply gravity to fall downwards. - { - if (mobj->player && !(mobj->fuse % 8) && (mobj->player->charflags & SF_MACHINE)) - { - fixed_t r = mobj->radius >> FRACBITS; - mobj_t *explosion = P_SpawnMobj( - mobj->x + (P_RandomRange(r, -r) << FRACBITS), - mobj->y + (P_RandomRange(r, -r) << FRACBITS), - mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), - MT_SONIC3KBOSSEXPLODE); - S_StartSound(explosion, sfx_s3kb4); - } - if (mobj->movedir == DMG_DROWNED) - P_SetObjectMomZ(mobj, -FRACUNIT / 2, true); // slower fall from drowning - else - P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true); - } - break; - case MT_METALSONIC_RACE: - { - if (!(mobj->fuse % 8)) - { - fixed_t r = mobj->radius >> FRACBITS; - mobj_t *explosion = P_SpawnMobj( - mobj->x + (P_RandomRange(r, -r) << FRACBITS), - mobj->y + (P_RandomRange(r, -r) << FRACBITS), - mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), - MT_SONIC3KBOSSEXPLODE); - S_StartSound(explosion, sfx_s3kb4); - } - P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true); - } - default: - break; - } + { + if (!P_MobjDeadThink(mobj)) + return; + } else { - if ((mobj->flags & MF_ENEMY) && (mobj->state->nextstate == mobj->info->spawnstate && mobj->tics == 1)) - mobj->flags2 &= ~MF2_FRET; - - // Angle-to-tracer to trigger a linedef exec - // See Linedef Exec 457 (Track mobj angle to point) - if ((mobj->eflags & MFE_TRACERANGLE) && mobj->tracer && mobj->extravalue2) - { - // mobj->lastlook - Don't disable behavior after first failure - // mobj->extravalue1 - Angle tolerance - // mobj->extravalue2 - Exec tag upon failure - // mobj->cvval - Allowable failure delay - // mobj->cvmem - Failure timer - - angle_t ang = mobj->angle - R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); - - // \todo account for distance between mobj and tracer - // Because closer mobjs can be facing beyond the angle tolerance - // yet tracer is still in the camera view - - // failure state: mobj is not facing tracer - // Reasaonable defaults: ANGLE_67h, ANGLE_292h - if (ang >= (angle_t)mobj->extravalue1 && ang <= ANGLE_MAX - (angle_t)mobj->extravalue1) - { - if (mobj->cvmem) - mobj->cvmem--; - else - { - INT32 exectag = mobj->extravalue2; // remember this before we erase the values - - if (mobj->lastlook) - mobj->cvmem = mobj->cusval; // reset timer for next failure - else - { - // disable after first failure - mobj->eflags &= ~MFE_TRACERANGLE; - mobj->lastlook = mobj->extravalue1 = mobj->extravalue2 = mobj->cvmem = mobj->cusval = 0; - } - - P_LinedefExecute(exectag, mobj, NULL); - } - } - else - mobj->cvmem = mobj->cusval; // reset failure timer - } - - switch (mobj->type) - { - case MT_WALLSPIKEBASE: - if (!mobj->target) { - P_RemoveMobj(mobj); - return; - } - mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|(mobj->target->frame & FF_FRAMEMASK); -#if 0 - if (mobj->angle != mobj->target->angle + ANGLE_90) // reposition if not the correct angle - { - mobj_t *target = mobj->target; // shortcut - const fixed_t baseradius = target->radius - (target->scale/2); //FixedMul(FRACUNIT/2, target->scale); - P_UnsetThingPosition(mobj); - mobj->x = target->x - P_ReturnThrustX(target, target->angle, baseradius); - mobj->y = target->y - P_ReturnThrustY(target, target->angle, baseradius); - P_SetThingPosition(mobj); - mobj->angle = target->angle + ANGLE_90; - } -#endif - break; - case MT_FALLINGROCK: - // Despawn rocks here in case zmovement code can't do so (blame slopes) - if (!mobj->momx && !mobj->momy && !mobj->momz - && ((mobj->eflags & MFE_VERTICALFLIP) ? - mobj->z + mobj->height >= mobj->ceilingz - : mobj->z <= mobj->floorz)) - { - P_RemoveMobj(mobj); - return; - } - P_MobjCheckWater(mobj); - break; - case MT_ARROW: - if (mobj->flags & MF_MISSILE) - { - // Calculate the angle of movement. - /* - momz - / | - / | - / | - 0------dist(momx,momy) - */ - - fixed_t dist = P_AproxDistance(mobj->momx, mobj->momy); - angle_t angle = R_PointToAngle2(0, 0, dist, mobj->momz); - - if (angle > ANG20 && angle <= ANGLE_180) - mobj->frame = 2; - else if (angle < ANG340 && angle > ANGLE_180) - mobj->frame = 0; - else - mobj->frame = 1; - - if (!(mobj->extravalue1) && (mobj->momz < 0)) - { - mobj->extravalue1 = 1; - S_StartSound(mobj, mobj->info->activesound); - } - if (leveltime & 1) - { - mobj_t *dust = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_PARTICLE); - dust->tics = 18; - dust->scalespeed = 4096; - dust->destscale = FRACUNIT/32; - } - } - else - mobj->flags2 ^= MF2_DONTDRAW; - break; - case MT_EMERALDSPAWN: - if (mobj->threshold) - { - mobj->threshold--; - - if (!mobj->threshold && !mobj->target && mobj->reactiontime) - { - mobj_t *emerald = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->reactiontime); - emerald->threshold = 42; - P_SetTarget(&mobj->target, emerald); - P_SetTarget(&emerald->target, mobj); - } - } - break; - case MT_BUGGLE: - mobj->eflags |= MFE_UNDERWATER; //P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn - { - if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 - && P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z - mobj->z) <= mobj->radius * 16) - { - // Home in on the target. - P_HomingAttack(mobj, mobj->tracer); - - if (mobj->z < mobj->floorz) - mobj->z = mobj->floorz; - - if (leveltime % mobj->info->painchance == 0) - S_StartSound(mobj, mobj->info->activesound); - - if ((statenum_t)(mobj->state-states) != mobj->info->seestate) - P_SetMobjState(mobj, mobj->info->seestate); - } - else - { - // Try to find a player - P_LookForPlayers(mobj, true, true, mobj->radius * 16); - mobj->momx >>= 1; - mobj->momy >>= 1; - mobj->momz >>= 1; - if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate) - P_SetMobjState(mobj, mobj->info->spawnstate); - } - } - break; - case MT_BUMBLEBORE: - { - statenum_t st = mobj->state-states; - if (st == S_BUMBLEBORE_FLY1 || st == S_BUMBLEBORE_FLY2) - { - if (!mobj->target) - P_SetMobjState(mobj, mobj->info->spawnstate); - else if (P_MobjFlip(mobj)*((mobj->z + (mobj->height>>1)) - (mobj->target->z + (mobj->target->height>>1))) > 0 - && R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) <= 32*FRACUNIT) - { - mobj->momx >>= 1; - mobj->momy >>= 1; - if (++mobj->movefactor == 4) - { - S_StartSound(mobj, mobj->info->seesound); - mobj->momx = mobj->momy = mobj->momz = 0; - mobj->flags = (mobj->flags|MF_PAIN) & ~MF_NOGRAVITY; - P_SetMobjState(mobj, mobj->info->meleestate); - } - } - else - mobj->movefactor = 0; - } - else if (st == S_BUMBLEBORE_RAISE || st == S_BUMBLEBORE_FALL2) // no _FALL1 because it's an 0-tic - { - if (P_IsObjectOnGround(mobj)) - { - S_StopSound(mobj); - S_StartSound(mobj, mobj->info->attacksound); - mobj->flags = (mobj->flags|MF_NOGRAVITY) & ~MF_PAIN; - mobj->momx = mobj->momy = mobj->momz = 0; - P_SetMobjState(mobj, mobj->info->painstate); - } - else - { - mobj->angle += ANGLE_22h; - mobj->frame = mobj->state->frame + ((mobj->tics & 2)>>1); - } - } - else if (st == S_BUMBLEBORE_STUCK2 && mobj->tics < TICRATE) - mobj->frame = mobj->state->frame + ((mobj->tics & 2)>>1); - } - break; - case MT_BIGMINE: - mobj->extravalue1 += 3; - mobj->extravalue1 %= 360; - P_UnsetThingPosition(mobj); - mobj->z += FINESINE(mobj->extravalue1*(FINEMASK+1)/360); - P_SetThingPosition(mobj); - break; - case MT_FLAME: - if (mobj->flags2 & MF2_BOSSNOTRAP) - { - if (!mobj->target || P_MobjWasRemoved(mobj->target)) - { - if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) - P_RemoveMobj(mobj->tracer); - P_RemoveMobj(mobj); - return; - } - mobj->z = mobj->target->z + mobj->target->momz; - if (!(mobj->eflags & MFE_VERTICALFLIP)) - mobj->z += mobj->target->height; - } - if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) - { - mobj->tracer->z = mobj->z + P_MobjFlip(mobj)*20*mobj->scale; - if (mobj->eflags & MFE_VERTICALFLIP) - mobj->tracer->z += mobj->height; - } - break; - case MT_WAVINGFLAG1: - case MT_WAVINGFLAG2: - { - fixed_t base = (leveltime<<(FRACBITS+1)); - mobj_t *seg = mobj->tracer, *prev = mobj; - mobj->movedir = mobj->angle - + ((((FINESINE((FixedAngle(base<<1)>>ANGLETOFINESHIFT) & FINEMASK) - + FINESINE((FixedAngle(base<<4)>>ANGLETOFINESHIFT) & FINEMASK))>>1) - + FINESINE((FixedAngle(base*9)>>ANGLETOFINESHIFT) & FINEMASK) - + FINECOSINE(((FixedAngle(base*9))>>ANGLETOFINESHIFT) & FINEMASK))<<12); //*2^12 - while (seg) - { - seg->movedir = seg->angle; - seg->angle = prev->movedir; - P_UnsetThingPosition(seg); - seg->x = prev->x + P_ReturnThrustX(prev, prev->angle, prev->radius); - seg->y = prev->y + P_ReturnThrustY(prev, prev->angle, prev->radius); - seg->z = prev->z + prev->height - (seg->scale>>1); - P_SetThingPosition(seg); - prev = seg; - seg = seg->tracer; - } - } - break; - case MT_SPINCUSHION: - if (mobj->target && mobj->state-states >= S_SPINCUSHION_AIM1 && mobj->state-states <= S_SPINCUSHION_AIM5) - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - break; - case MT_CRUSHCLAW: - if (mobj->state-states == S_CRUSHCLAW_STAY && mobj->target) - { - mobj_t *chain = mobj->target->target; - SINT8 sign = ((mobj->tics & 1) ? mobj->tics : -(SINT8)(mobj->tics)); - while (chain) - { - chain->z = chain->watertop + sign*mobj->scale; - sign = -sign; - chain = chain->target; - } - } - break; - case MT_SMASHINGSPIKEBALL: - mobj->momx = mobj->momy = 0; - if (mobj->state-states == S_SMASHSPIKE_FALL && P_IsObjectOnGround(mobj)) - { - P_SetMobjState(mobj, S_SMASHSPIKE_STOMP1); - S_StartSound(mobj, sfx_spsmsh); - } - else if (mobj->state-states == S_SMASHSPIKE_RISE2 && P_MobjFlip(mobj)*(mobj->z - mobj->movecount) >= 0) - { - mobj->momz = 0; - P_SetMobjState(mobj, S_SMASHSPIKE_FLOAT); - } - break; - case MT_HANGSTER: - { - statenum_t st = mobj->state-states; - //ghost image trail when flying down - if (st == S_HANGSTER_SWOOP1 || st == S_HANGSTER_SWOOP2) - { - P_SpawnGhostMobj(mobj); - //curve when in line with target, otherwise curve to avoid crashing into floor - if ((mobj->z - mobj->floorz <= 80*FRACUNIT) || (mobj->target && (mobj->z - mobj->target->z <= 80*FRACUNIT))) - P_SetMobjState(mobj, (st = S_HANGSTER_ARC1)); - } - - //swoop arc movement stuff - if (st == S_HANGSTER_ARC1) - { - A_FaceTarget(mobj); - P_Thrust(mobj, mobj->angle, 1*FRACUNIT); - } - else if (st == S_HANGSTER_ARC2) - P_Thrust(mobj, mobj->angle, 2*FRACUNIT); - else if (st == S_HANGSTER_ARC3) - P_Thrust(mobj, mobj->angle, 4*FRACUNIT); - //if movement has stopped while flying (like hitting a wall), fly up immediately - else if (st == S_HANGSTER_FLY1 && !mobj->momx && !mobj->momy) - { - mobj->extravalue1 = 0; - P_SetMobjState(mobj, S_HANGSTER_ARCUP1); - } - //after swooping back up, check for ceiling - else if ((st == S_HANGSTER_RETURN1 || st == S_HANGSTER_RETURN2) && mobj->momz == 0 && mobj->ceilingz == (mobj->z + mobj->height)) - P_SetMobjState(mobj, (st = S_HANGSTER_RETURN3)); - - //should you roost on a ceiling with F_SKY1 as its flat, disappear forever - if (st == S_HANGSTER_RETURN3 && mobj->momz == 0 && mobj->ceilingz == (mobj->z + mobj->height) - && mobj->subsector->sector->ceilingpic == skyflatnum - && mobj->subsector->sector->ceilingheight == mobj->ceilingz) - { - P_RemoveMobj(mobj); - return; - } - } - break; - case MT_LHRT: - mobj->momx = FixedMul(mobj->momx, mobj->extravalue2); - mobj->momy = FixedMul(mobj->momy, mobj->extravalue2); - break; - case MT_EGGCAPSULE: - if (!mobj->reactiontime) - { - // Target nearest player on your mare. - // (You can make it float up/down by adding MF_FLOAT, - // but beware level design pitfalls.) - fixed_t shortest = 1024*FRACUNIT; - INT32 i; - P_SetTarget(&mobj->target, NULL); - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo - && players[i].mare == mobj->threshold && players[i].spheres > 0) - { - fixed_t dist = P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y); - if (dist < shortest) - { - P_SetTarget(&mobj->target, players[i].mo); - shortest = dist; - } - } - } - break; - case MT_EGGMOBILE2_POGO: - if (!mobj->target - || !mobj->target->health - || mobj->target->state == &states[mobj->target->info->spawnstate] - || mobj->target->state == &states[mobj->target->info->raisestate]) - { - P_RemoveMobj(mobj); - return; - } - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z - mobj->height); - break; - case MT_HAMMER: - if (mobj->z <= mobj->floorz) - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_KOOPA: - P_KoopaThinker(mobj); - break; - case MT_FIREBALL: - if (P_AproxDistance(mobj->momx, mobj->momy) <= 16*FRACUNIT) // Once fireballs lose enough speed, kill them - { - P_KillMobj(mobj, NULL, NULL, 0); - return; - } - break; - case MT_REDRING: - if (((mobj->z < mobj->floorz) || (mobj->z + mobj->height > mobj->ceilingz)) - && mobj->flags & MF_MISSILE) - { - P_ExplodeMissile(mobj); - return; - } - break; - case MT_BOSSFLYPOINT: - return; - case MT_NIGHTSCORE: - mobj->color = (UINT8)(leveltime % SKINCOLOR_WHITE); - break; - case MT_JETFUME1: - { - fixed_t jetx, jety; - - if (!mobj->target // if you have no target - || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now - { // then remove yourself as well! - P_RemoveMobj(mobj); - return; - } - - jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); - jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); - - if (mobj->fuse == 56) // First one - { - P_UnsetThingPosition(mobj); - mobj->x = jetx; - mobj->y = jety; - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(38*FRACUNIT, mobj->target->scale); - else - mobj->z = mobj->target->z + FixedMul(38*FRACUNIT, mobj->target->scale); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - else if (mobj->fuse == 57) - { - P_UnsetThingPosition(mobj); - mobj->x = jetx + P_ReturnThrustX(mobj->target, mobj->target->angle-ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - mobj->y = jety + P_ReturnThrustY(mobj->target, mobj->target->angle-ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(12*FRACUNIT, mobj->target->scale); - else - mobj->z = mobj->target->z + FixedMul(12*FRACUNIT, mobj->target->scale); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - else if (mobj->fuse == 58) - { - P_UnsetThingPosition(mobj); - mobj->x = jetx + P_ReturnThrustX(mobj->target, mobj->target->angle+ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - mobj->y = jety + P_ReturnThrustY(mobj->target, mobj->target->angle+ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(12*FRACUNIT, mobj->target->scale); - else - mobj->z = mobj->target->z + FixedMul(12*FRACUNIT, mobj->target->scale); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - else if (mobj->fuse == 59) - { - boolean dashmod = ((mobj->target->flags & MF_PAIN) && (mobj->target->health <= mobj->target->info->damage)); - jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, -mobj->target->radius); - jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, -mobj->target->radius); - P_UnsetThingPosition(mobj); - mobj->x = jetx; - mobj->y = jety; - mobj->destscale = mobj->target->scale; - if (!(dashmod && mobj->target->state == states+S_METALSONIC_BOUNCE)) - { - mobj->destscale = (mobj->destscale + FixedDiv(R_PointToDist2(0, 0, mobj->target->momx, mobj->target->momy), 36*mobj->target->scale))/3; - } - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2; - else - mobj->z = mobj->target->z + mobj->target->height/2 - mobj->height/2; - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - if (dashmod) - { - mobj->color = SKINCOLOR_SUNSET; - if (mobj->target->movecount == 3 && !mobj->target->reactiontime && (mobj->target->movedir == 0 || mobj->target->movedir == 2)) - P_SpawnGhostMobj(mobj); - } - else - mobj->color = SKINCOLOR_ICY; - } - mobj->fuse++; - } - break; - case MT_JETFLAME: - { - if (!mobj->target // if you have no target - || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now - { // then remove yourself as well! - P_RemoveMobj(mobj); - return; - } - - P_UnsetThingPosition(mobj); - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - mobj->z = mobj->target->z - 50*mobj->target->scale; - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - break; - case MT_EGGROBO1: -#define SPECTATORRADIUS (96*mobj->scale) - { - if (!(mobj->flags2 & MF2_STRONGBOX)) - { - mobj->cusval = mobj->x; // eat my SOCs, p_mobj.h warning, we have lua now - mobj->cvmem = mobj->y; // ditto - mobj->movedir = mobj->angle; - mobj->threshold = P_MobjFlip(mobj)*10*mobj->scale; - if (mobj->threshold < 0) - mobj->threshold += (mobj->ceilingz - mobj->height); - else - mobj->threshold += mobj->floorz; - var1 = 4; - A_BossJetFume(mobj); - mobj->flags2 |= MF2_STRONGBOX; - } - - if (mobj->state == &states[mobj->info->deathstate]) // todo: make map actually set health to 0 for these - { - if (mobj->movecount) - { - if (!(--mobj->movecount)) - S_StartSound(mobj, mobj->info->deathsound); - } - else - { - mobj->momz += P_MobjFlip(mobj)*mobj->scale; - if (mobj->momz > 0) - { - if (mobj->z + mobj->momz > mobj->ceilingz + (1000<z + mobj->height + mobj->momz < mobj->floorz - (1000<cusval, basey = mobj->cvmem; - - if (mobj->spawnpoint && mobj->spawnpoint->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)) - { - angle_t sideang = mobj->movedir + ((mobj->spawnpoint->options & MTF_AMBUSH) ? ANGLE_90 : -ANGLE_90); - fixed_t oscillate = FixedMul(FINESINE(((leveltime*ANG1)>>(ANGLETOFINESHIFT+2)) & FINEMASK), 250*mobj->scale); - basex += P_ReturnThrustX(mobj, sideang, oscillate); - basey += P_ReturnThrustY(mobj, sideang, oscillate); - } - - mobj->z = mobj->threshold + FixedMul(FINESINE(((leveltime + mobj->movecount)*ANG2>>(ANGLETOFINESHIFT-2)) & FINEMASK), 8*mobj->scale); - if (mobj->state != &states[mobj->info->meleestate]) - { - boolean didmove = false; - - if (mobj->state == &states[mobj->info->spawnstate]) - { - UINT8 i; - fixed_t dist = INT32_MAX; - - for (i = 0; i < MAXPLAYERS; i++) - { - fixed_t compdist; - if (!playeringame[i]) - continue; - if (players[i].spectator) - continue; - if (!players[i].mo) - continue; - if (!players[i].mo->health) - continue; - if (P_PlayerInPain(&players[i])) - continue; - if (players[i].mo->z > mobj->z + mobj->height + 8*mobj->scale) - continue; - if (players[i].mo->z + players[i].mo->height < mobj->z - 8*mobj->scale) - continue; - compdist = P_AproxDistance( - players[i].mo->x + players[i].mo->momx - basex, - players[i].mo->y + players[i].mo->momy - basey); - if (compdist >= dist) - continue; - dist = compdist; - P_SetTarget(&mobj->target, players[i].mo); - } - - if (dist < (SPECTATORRADIUS<<1)) - { - didmove = true; - mobj->frame = 3 + ((leveltime & 2)>>1); - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - - if (P_AproxDistance( - mobj->x - basex, - mobj->y - basey) - < mobj->scale) - S_StartSound(mobj, mobj->info->seesound); - - P_TeleportMove(mobj, - (15*(mobj->x>>4)) + (basex>>4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS>>4), - (15*(mobj->y>>4)) + (basey>>4) + P_ReturnThrustY(mobj, mobj->angle, SPECTATORRADIUS>>4), - mobj->z); - } - else - { - angle_t diff = (mobj->movedir - mobj->angle); - if (diff > ANGLE_180) - diff = InvAngle(InvAngle(diff)/8); - else - diff /= 8; - mobj->angle += diff; - - dist = FINECOSINE(((leveltime + mobj->movecount)*ANG2>>(ANGLETOFINESHIFT-2)) & FINEMASK); - - if (abs(dist) < FRACUNIT/2) - mobj->frame = 0; - else - mobj->frame = (dist > 0) ? 1 : 2; - } - } - - if (!didmove) - { - if (P_AproxDistance(mobj->x - basex, mobj->y - basey) < mobj->scale) - P_TeleportMove(mobj, basex, basey, mobj->z); - else - P_TeleportMove(mobj, - (15*(mobj->x>>4)) + (basex>>4), - (15*(mobj->y>>4)) + (basey>>4), - mobj->z); - } - } - } - } - break; -#undef SPECTATORRADIUS - case MT_EGGROBO1JET: - { - if (!mobj->target || P_MobjWasRemoved(mobj->target) // if you have no target - || (mobj->target->health <= 0)) // or your target isn't a boss and it's popped now - { // then remove yourself as well! - P_RemoveMobj(mobj); - return; - } - - mobj->flags2 ^= MF2_DONTDRAW; - - P_UnsetThingPosition(mobj); - mobj->x = mobj->target->x + P_ReturnThrustX(mobj, mobj->target->angle+ANGLE_90, mobj->movefactor*mobj->target->scale) - P_ReturnThrustX(mobj, mobj->target->angle, 19*mobj->target->scale); - mobj->y = mobj->target->y + P_ReturnThrustY(mobj, mobj->target->angle+ANGLE_90, mobj->movefactor*mobj->target->scale) - P_ReturnThrustY(mobj, mobj->target->angle, 19*mobj->target->scale); - mobj->z = mobj->target->z; - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z += (mobj->target->height - mobj->height); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - break; - case MT_NIGHTSDRONE: - { - // variable setup - mobj_t *goalpost = NULL; - mobj_t *sparkle = NULL; - mobj_t *droneman = NULL; - - boolean flip = mobj->flags2 & MF2_OBJECTFLIP; - boolean topaligned = (mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE); - boolean middlealigned = (mobj->flags & MF_GRENADEBOUNCE) && !(mobj->flags & MF_SLIDEME); - boolean bottomoffsetted = !(mobj->flags & MF_SLIDEME) && !(mobj->flags & MF_GRENADEBOUNCE); - boolean flipchanged = false; - - fixed_t dronemanoffset, goaloffset, sparkleoffset, droneboxmandiff, dronemangoaldiff; - - if (mobj->target && mobj->target->type == MT_NIGHTSDRONE_GOAL) - { - goalpost = mobj->target; - if (goalpost->target && goalpost->target->type == MT_NIGHTSDRONE_SPARKLING) - sparkle = goalpost->target; - if (goalpost->tracer && goalpost->tracer->type == MT_NIGHTSDRONE_MAN) - droneman = goalpost->tracer; - } - - if (!goalpost || !sparkle || !droneman) - break; - - // did NIGHTSDRONE position, scale, flip, or flags change? all elements need to be synced - droneboxmandiff = max(mobj->height - droneman->height, 0); - dronemangoaldiff = max(droneman->height - goalpost->height, 0); - - if (!(goalpost->flags2 & MF2_OBJECTFLIP) && (mobj->flags2 & MF2_OBJECTFLIP)) - { - goalpost->eflags |= MFE_VERTICALFLIP; - goalpost->flags2 |= MF2_OBJECTFLIP; - sparkle->eflags |= MFE_VERTICALFLIP; - sparkle->flags2 |= MF2_OBJECTFLIP; - droneman->eflags |= MFE_VERTICALFLIP; - droneman->flags2 |= MF2_OBJECTFLIP; - flipchanged = true; - } - else if ((goalpost->flags2 & MF2_OBJECTFLIP) && !(mobj->flags2 & MF2_OBJECTFLIP)) - { - goalpost->eflags &= ~MFE_VERTICALFLIP; - goalpost->flags2 &= ~MF2_OBJECTFLIP; - sparkle->eflags &= ~MFE_VERTICALFLIP; - sparkle->flags2 &= ~MF2_OBJECTFLIP; - droneman->eflags &= ~MFE_VERTICALFLIP; - droneman->flags2 &= ~MF2_OBJECTFLIP; - flipchanged = true; - } - - if (goalpost->destscale != mobj->destscale - || goalpost->movefactor != mobj->z - || goalpost->friction != mobj->height - || flipchanged - || goalpost->threshold != (INT32)(mobj->flags & (MF_SLIDEME | MF_GRENADEBOUNCE))) - { - goalpost->destscale = sparkle->destscale = droneman->destscale = mobj->destscale; - - // straight copy-pasta from P_SpawnMapThing, case MT_NIGHTSDRONE - if (!flip) - { - if (topaligned) // Align droneman to top of hitbox - { - dronemanoffset = droneboxmandiff; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (middlealigned) // Align droneman to center of hitbox - { - dronemanoffset = droneboxmandiff / 2; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (bottomoffsetted) - { - dronemanoffset = 24*FRACUNIT; - goaloffset = dronemangoaldiff + dronemanoffset; - } - else - { - dronemanoffset = 0; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - - sparkleoffset = goaloffset - FixedMul(15*FRACUNIT, mobj->scale); - } - else - { - if (topaligned) // Align droneman to top of hitbox - { - dronemanoffset = 0; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (middlealigned) // Align droneman to center of hitbox - { - dronemanoffset = droneboxmandiff / 2; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - else if (bottomoffsetted) - { - dronemanoffset = droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); - goaloffset = dronemangoaldiff + dronemanoffset; - } - else - { - dronemanoffset = droneboxmandiff; - goaloffset = dronemangoaldiff / 2 + dronemanoffset; - } - - sparkleoffset = goaloffset + FixedMul(15*FRACUNIT, mobj->scale); - } - - P_TeleportMove(goalpost, mobj->x, mobj->y, mobj->z + goaloffset); - P_TeleportMove(sparkle, mobj->x, mobj->y, mobj->z + sparkleoffset); - if (goalpost->movefactor != mobj->z || goalpost->friction != mobj->height) - { - P_TeleportMove(droneman, mobj->x, mobj->y, mobj->z + dronemanoffset); - goalpost->movefactor = mobj->z; - goalpost->friction = mobj->height; - } - goalpost->threshold = mobj->flags & (MF_SLIDEME | MF_GRENADEBOUNCE); - } - else - { - if (goalpost->x != mobj->x || goalpost->y != mobj->y) - { - P_TeleportMove(goalpost, mobj->x, mobj->y, goalpost->z); - P_TeleportMove(sparkle, mobj->x, mobj->y, sparkle->z); - } - - if (droneman->x != mobj->x || droneman->y != mobj->y) - P_TeleportMove(droneman, mobj->x, mobj->y, - droneman->z >= mobj->floorz && droneman->z <= mobj->ceilingz ? droneman->z : mobj->z); - } - - // now toggle states! - // GOAL mode? - if (sparkle->state >= &states[S_NIGHTSDRONE_SPARKLING1] && sparkle->state <= &states[S_NIGHTSDRONE_SPARKLING16]) - { - INT32 i; - boolean bonustime = false; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) - { - bonustime = true; - break; - } - - if (!bonustime) - { - CONS_Debug(DBG_NIGHTSBASIC, "Removing goal post\n"); - if (goalpost && goalpost->state != &states[S_INVISIBLE]) - P_SetMobjState(goalpost, S_INVISIBLE); - if (sparkle && sparkle->state != &states[S_INVISIBLE]) - P_SetMobjState(sparkle, S_INVISIBLE); - } - } - // Invisible/bouncing mode. - else - { - INT32 i; - boolean bonustime = false; - fixed_t zcomp; - - // Bouncy bouncy! - if (!flip) - { - if (topaligned) - zcomp = droneboxmandiff + mobj->z; - else if (middlealigned) - zcomp = (droneboxmandiff / 2) + mobj->z; - else if (bottomoffsetted) - zcomp = mobj->z + FixedMul(24*FRACUNIT, mobj->scale); - else - zcomp = mobj->z; - } - else - { - if (topaligned) - zcomp = mobj->z; - else if (middlealigned) - zcomp = (droneboxmandiff / 2) + mobj->z; - else if (bottomoffsetted) - zcomp = mobj->z + droneboxmandiff - FixedMul(24*FRACUNIT, mobj->scale); - else - zcomp = mobj->z + droneboxmandiff; - } - - droneman->angle += ANG10; - if (!flip && droneman->z <= zcomp) - droneman->momz = FixedMul(5*FRACUNIT, droneman->scale); - else if (flip && droneman->z >= zcomp) - droneman->momz = FixedMul(-5*FRACUNIT, droneman->scale); - - // state switching logic - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) - { - bonustime = true; - break; - } - - if (bonustime) - { - CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n"); - if (!(droneman->flags2 & MF2_DONTDRAW)) - droneman->flags2 |= MF2_DONTDRAW; - if (goalpost->state == &states[S_INVISIBLE]) - P_SetMobjState(goalpost, mobjinfo[goalpost->type].meleestate); - if (sparkle->state == &states[S_INVISIBLE]) - P_SetMobjState(sparkle, mobjinfo[sparkle->type].meleestate); - } - else if (!G_IsSpecialStage(gamemap)) - { - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].powers[pw_carry] != CR_NIGHTSMODE) - { - bonustime = true; // variable reuse - break; - } - - if (bonustime) - { - // show droneman if at least one player is non-nights - if (goalpost->state != &states[S_INVISIBLE]) - P_SetMobjState(goalpost, S_INVISIBLE); - if (sparkle->state != &states[S_INVISIBLE]) - P_SetMobjState(sparkle, S_INVISIBLE); - if (droneman->state != &states[mobjinfo[droneman->type].meleestate]) - P_SetMobjState(droneman, mobjinfo[droneman->type].meleestate); - if (droneman->flags2 & MF2_DONTDRAW) - droneman->flags2 &= ~MF2_DONTDRAW; - } - else - { - // else, hide it - if (!(droneman->flags2 & MF2_DONTDRAW)) - droneman->flags2 |= MF2_DONTDRAW; - } - } - } - } - break; - case MT_PLAYER: - if (mobj->player) - P_PlayerMobjThinker(mobj); - return; - case MT_SKIM: - // check mobj against possible water content, before movement code - P_MobjCheckWater(mobj); - - // Keep Skim at water surface - if (mobj->z <= mobj->watertop) - { - mobj->flags |= MF_NOGRAVITY; - if (mobj->z < mobj->watertop) - { - if (mobj->watertop - mobj->z <= FixedMul(mobj->info->speed*FRACUNIT, mobj->scale)) - mobj->z = mobj->watertop; - else - mobj->momz = FixedMul(mobj->info->speed*FRACUNIT, mobj->scale); - } - } - else - { - mobj->flags &= ~MF_NOGRAVITY; - if (mobj->z > mobj->watertop && mobj->z - mobj->watertop < FixedMul(MAXSTEPMOVE, mobj->scale)) - mobj->z = mobj->watertop; - } - break; - case MT_RING: - case MT_REDTEAMRING: - case MT_BLUETEAMRING: - P_KillRingsInLava(mobj); - if (P_MobjWasRemoved(mobj)) - return; - /* FALLTHRU */ - case MT_COIN: - case MT_BLUESPHERE: - case MT_BOMBSPHERE: - case MT_NIGHTSCHIP: - case MT_NIGHTSSTAR: - // No need to check water. Who cares? - P_RingThinker(mobj); - if (mobj->flags2 & MF2_NIGHTSPULL) - P_NightsItemChase(mobj); - else - A_AttractChase(mobj); - return; - // Flung items - case MT_FLINGRING: - P_KillRingsInLava(mobj); - if (P_MobjWasRemoved(mobj)) - return; - /* FALLTHRU */ - case MT_FLINGCOIN: - case MT_FLINGBLUESPHERE: - case MT_FLINGNIGHTSCHIP: - if (mobj->flags2 & MF2_NIGHTSPULL) - P_NightsItemChase(mobj); - else - A_AttractChase(mobj); - break; - case MT_EMBLEM: - if (mobj->flags2 & MF2_NIGHTSPULL) - P_NightsItemChase(mobj); - break; - case MT_SHELL: - if (mobj->threshold && mobj->threshold != TICRATE) - mobj->threshold--; - - if (mobj->threshold >= TICRATE) - { - mobj->angle += ((mobj->movedir == 1) ? ANGLE_22h : ANGLE_337h); - P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), (mobj->info->speed*mobj->scale)); - } - break; - case MT_TURRET: - P_MobjCheckWater(mobj); - P_CheckPosition(mobj, mobj->x, mobj->y); - if (P_MobjWasRemoved(mobj)) - return; - mobj->floorz = tmfloorz; - mobj->ceilingz = tmceilingz; - mobj->floorrover = tmfloorrover; - mobj->ceilingrover = tmceilingrover; - - if ((mobj->eflags & MFE_UNDERWATER) && mobj->health > 0) - { - P_SetMobjState(mobj, mobj->info->deathstate); - mobj->health = 0; - mobj->flags2 &= ~MF2_FIRING; - } - else if (mobj->health > 0 && mobj->z + mobj->height > mobj->ceilingz) // Crushed - { - INT32 i,j; - fixed_t ns; - fixed_t x,y,z; - mobj_t *mo2; - - z = mobj->subsector->sector->floorheight + FixedMul(64*FRACUNIT, mobj->scale); - for (j = 0; j < 2; j++) - { - for (i = 0; i < 32; i++) - { - const angle_t fa = (i*FINEANGLES/16) & FINEMASK; - ns = FixedMul(64 * FRACUNIT, mobj->scale); - x = mobj->x + FixedMul(FINESINE(fa),ns); - y = mobj->y + FixedMul(FINECOSINE(fa),ns); - - mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); - ns = FixedMul(16 * FRACUNIT, mobj->scale); - mo2->momx = FixedMul(FINESINE(fa),ns); - mo2->momy = FixedMul(FINECOSINE(fa),ns); - } - z -= FixedMul(32*FRACUNIT, mobj->scale); - } - P_SetMobjState(mobj, mobj->info->deathstate); - mobj->health = 0; - mobj->flags2 &= ~MF2_FIRING; - } - break; - case MT_BLUEFLAG: - case MT_REDFLAG: - { - sector_t *sec2; - sec2 = P_ThingOnSpecial3DFloor(mobj); - if ((sec2 && GETSECSPECIAL(sec2->special, 4) == 2) || (GETSECSPECIAL(mobj->subsector->sector->special, 4) == 2)) - mobj->fuse = 1; // Return to base. - break; - } - case MT_CANNONBALL: -#ifdef FLOORSPLATS - R_AddFloorSplat(mobj->tracer->subsector, mobj->tracer, "TARGET", mobj->tracer->x, - mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE); -#endif - break; - case MT_SPINDUST: // Spindash dust - mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000 - mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same - //mobj->momz = mobj->momz+P_MobjFlip(mobj)/3; // no meaningful change in value to be frank - if (mobj->state >= &states[S_SPINDUST_BUBBLE1] && mobj->state <= &states[S_SPINDUST_BUBBLE4]) // bubble dust! - { - P_MobjCheckWater(mobj); - if (mobj->watertop != mobj->subsector->sector->floorheight - 1000*FRACUNIT - && mobj->z+mobj->height >= mobj->watertop - 5*FRACUNIT) - mobj->flags2 |= MF2_DONTDRAW; - } - break; - case MT_TRAINDUSTSPAWNER: - if (leveltime % 5 == 0) { - mobj_t *traindust = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PARTICLE); - traindust->flags = MF_SCENERY; - P_SetMobjState(traindust, S_TRAINDUST); - traindust->frame = P_RandomRange(0, 8) | FF_TRANS90; - traindust->angle = mobj->angle; - traindust->tics = TICRATE * 4; - traindust->destscale = FRACUNIT * 64; - traindust->scalespeed = FRACUNIT / 24; - P_SetScale(traindust, FRACUNIT * 6); - } - break; - case MT_TRAINSTEAMSPAWNER: - if (leveltime % 5 == 0) { - mobj_t *steam = P_SpawnMobj(mobj->x + FRACUNIT*P_SignedRandom() / 2, mobj->y + FRACUNIT*P_SignedRandom() / 2, mobj->z, MT_PARTICLE); - P_SetMobjState(steam, S_TRAINSTEAM); - steam->frame = P_RandomRange(0, 1) | FF_TRANS90; - steam->tics = TICRATE * 8; - steam->destscale = FRACUNIT * 64; - steam->scalespeed = FRACUNIT / 8; - P_SetScale(steam, FRACUNIT * 16); - steam->momx = P_SignedRandom() * 32; - steam->momy = -64 * FRACUNIT; - steam->momz = 2 * FRACUNIT; - } - break; - case MT_CANARIVORE_GAS: - { - fixed_t momz; - - if (mobj->flags2 & MF2_AMBUSH) - { - mobj->momx = FixedMul(mobj->momx, 50 * FRACUNIT / 51); - mobj->momy = FixedMul(mobj->momy, 50 * FRACUNIT / 51); - break; - } - - if (mobj->eflags & MFE_VERTICALFLIP) - { - if ((mobj->z + mobj->height + mobj->momz) <= mobj->ceilingz) - break; - } - else - { - if ((mobj->z + mobj->momz) >= mobj->floorz) - break; - } - - momz = abs(mobj->momz); - if (R_PointToDist2(0, 0, mobj->momx, mobj->momy) < momz) - P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), momz); - mobj->flags2 |= MF2_AMBUSH; - break; - } - case MT_SALOONDOOR: - { - fixed_t x = mobj->tracer->x; - fixed_t y = mobj->tracer->y; - fixed_t z = mobj->tracer->z; - angle_t oang = FixedAngle(mobj->extravalue1); - angle_t fa = (oang >> ANGLETOFINESHIFT) & FINEMASK; - fixed_t c0 = -96*FINECOSINE(fa); - fixed_t s0 = -96*FINESINE(fa); - angle_t fma; - fixed_t c, s; - angle_t angdiff; - - // Adjust angular speed - fixed_t da = AngleFixed(mobj->angle - oang); - if (da > 180*FRACUNIT) - da -= 360*FRACUNIT; - mobj->extravalue2 = 8*(mobj->extravalue2 - da/32)/9; - - // Update angle - mobj->angle += FixedAngle(mobj->extravalue2); - - angdiff = mobj->angle - FixedAngle(mobj->extravalue1); - if (angdiff > (ANGLE_90 - ANG2) && angdiff < ANGLE_180) - { - mobj->angle = FixedAngle(mobj->extravalue1) + (ANGLE_90 - ANG2); - mobj->extravalue2 /= 2; - } - else if (angdiff < (ANGLE_270 + ANG2) && angdiff >= ANGLE_180) - { - mobj->angle = FixedAngle(mobj->extravalue1) + (ANGLE_270 + ANG2); - mobj->extravalue2 /= 2; - } - - // Update position - fma = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK; - c = 48*FINECOSINE(fma); - s = 48*FINESINE(fma); - P_TeleportMove(mobj, x + c0 + c, y + s0 + s, z); - break; - } - case MT_MINECARTSPAWNER: - P_HandleMinecartSegments(mobj); - if (!mobj->fuse || mobj->fuse > TICRATE) - break; - if (mobj->fuse == 2) - { - mobj->fuse = 0; - break; - } - mobj->flags2 ^= MF2_DONTDRAW; - break; - case MT_LAVAFALLROCK: - if (P_IsObjectOnGround(mobj)) - P_RemoveMobj(mobj); - break; - case MT_PYREFLY: - { - fixed_t hdist; - - mobj->extravalue1 = (mobj->extravalue1 + 3) % 360; - mobj->z += FINESINE(((mobj->extravalue1*ANG1) >> ANGLETOFINESHIFT) & FINEMASK); - - if (!(mobj->flags2 & MF2_BOSSNOTRAP)) - P_LookForPlayers(mobj, true, false, 1500*FRACUNIT); - - if (!mobj->target) - break; - - if (mobj->extravalue2 == 1) - P_PyreFlyBurn(mobj, 0, 20, MT_SMOKE, 4*FRACUNIT); - else if (mobj->extravalue2 == 2) - { - INT32 fireradius = min(100 - mobj->fuse, 52); - P_PyreFlyBurn(mobj, P_RandomRange(0, fireradius)*FRACUNIT, 20, MT_FLAMEPARTICLE, 4*FRACUNIT); - P_PyreFlyBurn(mobj, fireradius*FRACUNIT, 40, MT_PYREFLY_FIRE, 0); - } - - hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - - if (hdist > 1500*FRACUNIT) - { - mobj->flags2 &= ~MF2_BOSSNOTRAP; - P_SetTarget(&mobj->target, NULL); - break; - } - - if (!(mobj->flags2 & MF2_BOSSNOTRAP) && hdist <= 450*FRACUNIT) - mobj->flags2 |= MF2_BOSSNOTRAP; - - if (!(mobj->flags2 & MF2_BOSSNOTRAP)) - break; - - if (hdist < 1000*FRACUNIT) - { - //Aim for player z position. If too close to floor/ceiling, aim just above/below them. - fixed_t destz = min(max(mobj->target->z, mobj->target->floorz + 70*FRACUNIT), mobj->target->ceilingz - 80*FRACUNIT - mobj->height); - fixed_t dist = P_AproxDistance(hdist, destz - mobj->z); - P_InstaThrust(mobj, R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y), 2*FRACUNIT); - mobj->momz = FixedMul(FixedDiv(destz - mobj->z, dist), 2*FRACUNIT); - } - else - { - mobj->momx = 0; - mobj->momy = 0; - mobj->momz = 0; - } - break; - } - case MT_PTERABYTE: - { - if (mobj->extravalue1 & 4) // Cooldown after grabbing - { - if (mobj->movefactor) - mobj->movefactor--; - else - { - P_SetTarget(&mobj->target, NULL); - mobj->extravalue1 &= 3; - } - } - - if ((mobj->extravalue1 & 3) == 0) // Hovering - { - fixed_t vdist, hdist, time; - fixed_t hspeed = 3*mobj->info->speed; - angle_t fa; - - var1 = 1; - var2 = 0; - A_CapeChase(mobj); - - if (mobj->target) - break; // Still carrying a player or in cooldown - - P_LookForPlayers(mobj, true, false, 256*FRACUNIT); - - if (!mobj->target) - break; - - if (mobj->target->player->powers[pw_flashing]) - { - P_SetTarget(&mobj->target, NULL); - break; - } - - vdist = mobj->z - mobj->target->z - mobj->target->height; - if (P_MobjFlip(mobj)*vdist <= 0) - { - P_SetTarget(&mobj->target, NULL); - break; - } - - hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - if (hdist > 450*FRACUNIT) - { - P_SetTarget(&mobj->target, NULL); - break; - } - - P_SetMobjState(mobj, S_PTERABYTE_SWOOPDOWN); - mobj->extravalue1++; - S_StartSound(mobj, mobj->info->attacksound); - time = FixedDiv(hdist, hspeed); - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - fa = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK; - mobj->momx = FixedMul(FINECOSINE(fa), hspeed); - mobj->momy = FixedMul(FINESINE(fa), hspeed); - mobj->momz = -2*FixedDiv(vdist, time); - mobj->extravalue2 = -FixedDiv(mobj->momz, time); //Z accel - mobj->movecount = time >> FRACBITS; - mobj->reactiontime = mobj->movecount; - } - else if ((mobj->extravalue1 & 3) == 1) // Swooping - { - mobj->reactiontime--; - mobj->momz += mobj->extravalue2; - if (mobj->reactiontime) - break; - - if (mobj->state - states == S_PTERABYTE_SWOOPDOWN) - { - P_SetMobjState(mobj, S_PTERABYTE_SWOOPUP); - mobj->reactiontime = mobj->movecount; - } - else if (mobj->state - states == S_PTERABYTE_SWOOPUP) - { - P_SetMobjState(mobj, S_PTERABYTE_FLY1); - mobj->extravalue1++; - if (mobj->target && mobj->target->tracer != mobj) - P_SetTarget(&mobj->target, NULL); // Failed to grab the target - mobj->momx = mobj->momy = mobj->momz = 0; - } - } - else // Returning - { - var1 = 2*mobj->info->speed; - var2 = 1; - A_HomingChase(mobj); - if (P_AproxDistance(mobj->x - mobj->tracer->x, mobj->y - mobj->tracer->y) <= mobj->info->speed) - { - mobj->extravalue1 -= 2; - mobj->momx = mobj->momy = mobj->momz = 0; - } - } - break; - } - case MT_DRAGONBOMBER: - { -#define DRAGONTURNSPEED ANG2 - mobj->movecount = (mobj->movecount + 9) % 360; - P_SetObjectMomZ(mobj, 4*FINESINE(((mobj->movecount*ANG1) >> ANGLETOFINESHIFT) & FINEMASK), false); - if (mobj->threshold > 0) // are we dropping mines? - { - mobj->threshold--; - if (mobj->threshold == 0) // if the timer hits 0, look for a mine to drop! - { - mobj_t *segment = mobj; - while (segment->tracer != NULL && !P_MobjWasRemoved(segment->tracer) && segment->tracer->state == &states[segment->tracer->info->spawnstate]) - { - segment = segment->tracer; - } - if (segment != mobj) // found an unactivated segment? - { - mobj_t *mine = P_SpawnMobjFromMobj(segment, 0, 0, 0, segment->info->painchance); - mine->angle = segment->angle; - P_InstaThrust(mine, mobj->angle, P_AproxDistance(mobj->momx, mobj->momy) >> 1); - P_SetObjectMomZ(mine, -2*FRACUNIT, true); - S_StartSound(mine, mine->info->seesound); - P_SetMobjState(segment, segment->info->raisestate); - mobj->threshold = mobj->info->painchance; - } - } - } - if (mobj->target != NULL) // Are we chasing a player? - { - fixed_t dist = P_AproxDistance(mobj->x - mobj->target->x, mobj->y - mobj->target->y); - if (dist > 2000 * mobj->scale) // Not anymore! - P_SetTarget(&mobj->target, NULL); - else - { - fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); - fixed_t z = mobj->target->z + (mobj->height >> 1) + (mobj->flags & MFE_VERTICALFLIP ? -128*mobj->scale : 128*mobj->scale + mobj->target->height); - angle_t diff = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) - mobj->angle; - if (diff > ANGLE_180) - mobj->angle -= DRAGONTURNSPEED; - else - mobj->angle += DRAGONTURNSPEED; - if (!mobj->threshold && dist < 512 * mobj->scale) // Close enough to drop bombs - { - mobj->threshold = mobj->info->painchance; - } - mobj->momz += max(min(z - mobj->z, vspeed), -vspeed); - } - } - else // Can we find a player to chase? - { - if (mobj->tracer == NULL || mobj->tracer->state != &states[mobj->tracer->info->spawnstate] - || !P_LookForPlayers(mobj, true, false, 2000*mobj->scale)) // if not, circle around the spawnpoint - { - if (!mobj->spawnpoint) // unless we don't have one, in which case uhhh just circle around wherever we currently are I guess?? - mobj->angle += DRAGONTURNSPEED; - else - { - fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); - fixed_t x = mobj->spawnpoint->x << FRACBITS; - fixed_t y = mobj->spawnpoint->y << FRACBITS; - fixed_t z = mobj->spawnpoint->z << FRACBITS; - angle_t diff = R_PointToAngle2(mobj->x, mobj->y, x, y) - mobj->angle; - if (diff > ANGLE_180) - mobj->angle -= DRAGONTURNSPEED; - else - mobj->angle += DRAGONTURNSPEED; - mobj->momz += max(min(z - mobj->z, vspeed), -vspeed); - } - } - } - P_InstaThrust(mobj, mobj->angle, FixedMul(mobj->info->speed, mobj->scale)); -#undef DRAGONTURNSPEED - } - break; - case MT_MINUS: -#ifdef ROTSPRITE - { - if (P_IsObjectOnGround(mobj)) - mobj->rollangle = 0; - else - mobj->rollangle = R_PointToAngle2(0, 0, mobj->momz, (mobj->scale << 1) - min(abs(mobj->momz), mobj->scale << 1)); - } -#endif - break; - case MT_SPINFIRE: - if (mobj->flags & MF_NOGRAVITY) - { - if (mobj->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->ceilingz - mobj->height; - else - mobj->z = mobj->floorz; - } - else if ((!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z <= mobj->floorz) - || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z+mobj->height >= mobj->ceilingz)) - { - mobj->flags |= MF_NOGRAVITY; - mobj->momx = 8; // this is a hack which is used to ensure it still behaves as a missile and can damage others - mobj->momy = mobj->momz = 0; - mobj->z = ((mobj->eflags & MFE_VERTICALFLIP) ? mobj->ceilingz-mobj->height : mobj->floorz); - } - /* FALLTHRU */ - default: - // check mobj against possible water content, before movement code - P_MobjCheckWater(mobj); - - // Extinguish fire objects in water - if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL - && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) - { - P_KillMobj(mobj, NULL, NULL, 0); - return; - } - break; - } + if (!P_MobjRegularThink(mobj)) + return; } if (P_MobjWasRemoved(mobj)) return; - if (mobj->flags2 & MF2_FIRING && mobj->target && mobj->health > 0) - { - if (mobj->state->action.acp1 == (actionf_p1)A_Boss1Laser) - { - if (mobj->state->tics > 1) - { - var1 = mobj->state->var1; - var2 = mobj->state->var2 & 65535; - mobj->state->action.acp1(mobj); - } - } - else if (leveltime & 1) // Fire mode - { - mobj_t *missile; - - if (mobj->target->player && mobj->target->player->powers[pw_carry] == CR_NIGHTSMODE) - { - fixed_t oldval = mobjinfo[mobj->extravalue1].speed; - - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x+mobj->target->momx, mobj->target->y+mobj->target->momy); - mobjinfo[mobj->extravalue1].speed = FixedMul(60*FRACUNIT, mobj->scale); - missile = P_SpawnMissile(mobj, mobj->target, mobj->extravalue1); - mobjinfo[mobj->extravalue1].speed = oldval; - } - else - { - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - missile = P_SpawnMissile(mobj, mobj->target, mobj->extravalue1); - } - - if (missile) - { - if (mobj->flags2 & MF2_SUPERFIRE) - missile->flags2 |= MF2_SUPERFIRE; - - if (mobj->info->attacksound) - S_StartSound(missile, mobj->info->attacksound); - } - } - else - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - } + if (mobj->flags2 & MF2_FIRING) + P_FiringThink(mobj); if (mobj->flags & MF_AMBIENT) { @@ -9830,216 +10188,8 @@ void P_MobjThinker(mobj_t *mobj) } // Check fuse - if (mobj->fuse) - { - - if (mobj->type == MT_SNAPPER_HEAD || mobj->type == MT_SNAPPER_LEG || mobj->type == MT_MINECARTSEG) - mobj->flags2 ^= MF2_DONTDRAW; - - mobj->fuse--; - if (!mobj->fuse) - { - subsector_t *ss; - fixed_t x, y, z; - mobj_t *flagmo, *newmobj; - -#ifdef HAVE_BLUA - if (LUAh_MobjFuse(mobj) || P_MobjWasRemoved(mobj)) - ; - else -#endif - if (mobj->info->flags & MF_MONITOR) - { - // Special case for ALL monitors. - // If a box's speed is nonzero, it's allowed to respawn as a WRM/SRM. - if (mobj->info->speed != 0 && (mobj->flags2 & (MF2_AMBUSH|MF2_STRONGBOX))) - { - mobjtype_t spawnchance[64]; - INT32 numchoices = 0, i = 0; - -// This define should make it a lot easier to organize and change monitor weights -#define SETMONITORCHANCES(type, strongboxamt, weakboxamt) \ -for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) spawnchance[numchoices++] = type - - // Type SRM WRM - SETMONITORCHANCES(MT_SNEAKERS_BOX, 0, 10); // Super Sneakers - SETMONITORCHANCES(MT_INVULN_BOX, 2, 0); // Invincibility - SETMONITORCHANCES(MT_WHIRLWIND_BOX, 3, 8); // Whirlwind Shield - SETMONITORCHANCES(MT_ELEMENTAL_BOX, 3, 8); // Elemental Shield - SETMONITORCHANCES(MT_ATTRACT_BOX, 2, 0); // Attraction Shield - SETMONITORCHANCES(MT_FORCE_BOX, 3, 3); // Force Shield - SETMONITORCHANCES(MT_ARMAGEDDON_BOX, 2, 0); // Armageddon Shield - SETMONITORCHANCES(MT_MIXUP_BOX, 0, 1); // Teleporters - SETMONITORCHANCES(MT_RECYCLER_BOX, 0, 1); // Recycler - SETMONITORCHANCES(MT_1UP_BOX, 1, 1); // 1-Up - // ======================================= - // Total 16 32 - -#undef SETMONITORCHANCES - - i = P_RandomKey(numchoices); // Gotta love those random numbers! - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]); - } - else - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); - - // Transfer flags2 (ambush, strongbox, objectflip) - newmobj->flags2 = mobj->flags2; - P_RemoveMobj(mobj); // make sure they disappear - return; - } - else switch (mobj->type) - { - // gargoyle and snowman handled in P_PushableThinker, not here - case MT_THROWNGRENADE: - case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: - P_SetMobjState(mobj, mobj->info->deathstate); - break; - case MT_LHRT: - P_KillMobj(mobj, NULL, NULL, 0); - break; - case MT_BLUEFLAG: - case MT_REDFLAG: - if (mobj->spawnpoint) - { - x = mobj->spawnpoint->x << FRACBITS; - y = mobj->spawnpoint->y << FRACBITS; - ss = R_PointInSubsector(x, y); - if (mobj->spawnpoint->options & MTF_OBJECTFLIP) - { - z = ss->sector->ceilingheight - mobjinfo[mobj->type].height; - if (mobj->spawnpoint->options >> ZSHIFT) - z -= (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; - } - else - { - z = ss->sector->floorheight; - if (mobj->spawnpoint->options >> ZSHIFT) - z += (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; - } - flagmo = P_SpawnMobj(x, y, z, mobj->type); - flagmo->spawnpoint = mobj->spawnpoint; - if (mobj->spawnpoint->options & MTF_OBJECTFLIP) - { - flagmo->eflags |= MFE_VERTICALFLIP; - flagmo->flags2 |= MF2_OBJECTFLIP; - } - - if (mobj->type == MT_REDFLAG) - { - if (!(mobj->flags2 & MF2_JUSTATTACKED)) - CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x85, M_GetText("Red flag"), 0x80); - - // Assumedly in splitscreen players will be on opposing teams - if (players[consoleplayer].ctfteam == 1 || splitscreen) - S_StartSound(NULL, sfx_hoop1); - else if (players[consoleplayer].ctfteam == 2) - S_StartSound(NULL, sfx_hoop3); - - redflag = flagmo; - } - else // MT_BLUEFLAG - { - if (!(mobj->flags2 & MF2_JUSTATTACKED)) - CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x84, M_GetText("Blue flag"), 0x80); - - // Assumedly in splitscreen players will be on opposing teams - if (players[consoleplayer].ctfteam == 2 || splitscreen) - S_StartSound(NULL, sfx_hoop1); - else if (players[consoleplayer].ctfteam == 1) - S_StartSound(NULL, sfx_hoop3); - - blueflag = flagmo; - } - } - P_RemoveMobj(mobj); - return; - case MT_FANG: - if (mobj->flags2 & MF2_SLIDEPUSH) - { - var1 = 0; - var2 = 0; - A_BossDeath(mobj); - return; - } - P_SetMobjState(mobj, mobj->state->nextstate); - if (P_MobjWasRemoved(mobj)) - return; - break; - case MT_METALSONIC_BATTLE: - break; // don't remove - case MT_SPIKE: - P_SetMobjState(mobj, mobj->state->nextstate); - mobj->fuse = mobj->info->speed; - if (mobj->spawnpoint) - mobj->fuse += mobj->spawnpoint->angle; - break; - case MT_WALLSPIKE: - P_SetMobjState(mobj, mobj->state->nextstate); - mobj->fuse = mobj->info->speed; - if (mobj->spawnpoint) - mobj->fuse += (mobj->spawnpoint->angle/360); - break; - case MT_NIGHTSCORE: - P_RemoveMobj(mobj); - return; - case MT_LAVAFALL: - if (mobj->state - states == S_LAVAFALL_DORMANT) - { - mobj->fuse = 30; - P_SetMobjState(mobj, S_LAVAFALL_TELL); - S_StartSound(mobj, mobj->info->seesound); - } - else if (mobj->state - states == S_LAVAFALL_TELL) - { - mobj->fuse = 40; - P_SetMobjState(mobj, S_LAVAFALL_SHOOT); - S_StopSound(mobj); - S_StartSound(mobj, mobj->info->attacksound); - } - else - { - mobj->fuse = 30; - P_SetMobjState(mobj, S_LAVAFALL_DORMANT); - S_StopSound(mobj); - } - return; - case MT_PYREFLY: - if (mobj->health <= 0) - break; - - mobj->extravalue2 = (mobj->extravalue2 + 1) % 3; - if (mobj->extravalue2 == 0) - { - P_SetMobjState(mobj, mobj->info->spawnstate); - mobj->fuse = 100; - S_StopSound(mobj); - S_StartSound(mobj, sfx_s3k8c); - } - else if (mobj->extravalue2 == 1) - { - mobj->fuse = 50; - S_StartSound(mobj, sfx_s3ka3); - } - else - { - P_SetMobjState(mobj, mobj->info->meleestate); - mobj->fuse = 100; - S_StopSound(mobj); - S_StartSound(mobj, sfx_s3kc2l); - } - return; - case MT_PLAYER: - break; // don't remove - default: - P_SetMobjState(mobj, mobj->info->xdeathstate); // will remove the mobj if S_NULL. - break; - // Looking for monitors? They moved to a special condition above. - } - if (P_MobjWasRemoved(mobj)) - return; - } - } + if (mobj->fuse && !P_FuseThink(mobj)) + return; I_Assert(mobj != NULL); I_Assert(!P_MobjWasRemoved(mobj)); @@ -11188,7 +11338,7 @@ void P_RespawnSpecials(void) } //CTF rings should continue to respawn as normal rings outside of CTF. - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) { if (i == MT_REDTEAMRING || i == MT_BLUETEAMRING) i = MT_RING; @@ -11259,7 +11409,10 @@ void P_SpawnPlayer(INT32 playernum) { p->outofcoop = false; if (netgame && p->jointime < 1) - p->spectator = true; + { + // Averted by GTR_NOSPECTATORSPAWN. + p->spectator = (gametyperules & GTR_NOSPECTATORSPAWN) ? false : true; + } else if (multiplayer && !netgame) { // If you're in a team game and you don't have a team assigned yet... @@ -11302,7 +11455,7 @@ void P_SpawnPlayer(INT32 playernum) p->skincolor = skincolor_blueteam; } - if ((netgame || multiplayer) && (gametype != GT_COOP || leveltime) && !p->spectator && !(maptol & TOL_NIGHTS)) + if ((netgame || multiplayer) && ((gametyperules & GTR_SPAWNINVUL) || leveltime) && !p->spectator && !(maptol & TOL_NIGHTS)) p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER); @@ -11707,7 +11860,7 @@ static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) else if (mthing->type == mobjinfo[MT_EMERHUNT].doomednum) { // Emerald Hunt is Coop only. Don't spawn the emerald yet, but save the spawnpoint for later. - if (gametype == GT_COOP && numhuntemeralds < MAXHUNTEMERALDS) + if ((gametyperules & GTR_EMERALDHUNT) && numhuntemeralds < MAXHUNTEMERALDS) huntemeralds[numhuntemeralds++] = mthing; return true; } @@ -11740,7 +11893,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) if (!cv_powerstones.value) return false; - if (!(gametype == GT_MATCH || gametype == GT_CTF)) + if (!(gametyperules & GTR_MATCHEMERALDS)) return false; runemeraldmanager = true; @@ -11754,7 +11907,7 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) break; case MT_TOKEN: - if (gametype != GT_COOP && gametype != GT_COMPETITION) + if (!(gametyperules & GTR_EMERALDTOKENS)) return false; // Gametype's not right if (tokenbits == 30) @@ -11784,20 +11937,20 @@ static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) return false; } - if (!G_PlatformGametype()) - { - if ((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS)) - return false; // No enemies in ringslinger modes + if (((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS)) && !(gametyperules & GTR_SPAWNENEMIES)) + return false; // No enemies in ringslinger modes - if (i == MT_SIGN || i == MT_STARPOST) - return false; // Don't spawn exit signs or starposts in wrong game modes - } + if (!(gametyperules & GTR_ALLOWEXIT) && (i == MT_SIGN)) + return false; // Don't spawn exit signs in wrong game modes + + if (!G_PlatformGametype() && (i == MT_STARPOST)) + return false; // Don't spawn starposts in wrong game modes if (!G_RingSlingerGametype() || !cv_specialrings.value) if (P_WeaponOrPanel(i)) return false; // Don't place weapons/panels in non-ringslinger modes - if (gametype != GT_CTF) // CTF specific things + if (!(gametyperules & GTR_TEAMFLAGS)) // CTF specific things { if (i == MT_BLUEFLAG || i == MT_REDFLAG) return false; // No flags in non-CTF modes! @@ -11845,7 +11998,7 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) // Yeah, this is a dirty hack. if ((mobjinfo[i].flags & (MF_MONITOR|MF_GRENADEBOUNCE)) == MF_MONITOR) { - if (gametype == GT_COMPETITION || gametype == GT_RACE) + if (gametyperules & GTR_RACE) { // Set powerup boxes to user settings for competition. switch (cv_competitionboxes.value) @@ -11889,7 +12042,7 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) return MT_NIGHTSCHIP; } - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMS)) { if (i == MT_BLUETEAMRING || i == MT_REDTEAMRING) return MT_RING; @@ -13372,7 +13525,7 @@ void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) { INT32 numitems = (mthing->type & 1) ? 16 : 8; fixed_t size = (mthing->type & 1) ? 192*FRACUNIT : 96*FRACUNIT; - mobjtype_t itemtypes[1] = { (mthing->type & 1) ? MT_RING : MT_BLUESPHERE }; + mobjtype_t itemtypes[1] = { (mthing->type < 606) ? MT_RING : MT_BLUESPHERE }; P_SpawnItemCircle(mthing, itemtypes, 1, numitems, size, bonustime); return; } diff --git a/src/p_mobj.h b/src/p_mobj.h index a272003c1..92160d9e2 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -279,9 +279,7 @@ typedef struct mobj_s // More drawing info: to determine current sprite. angle_t angle; // orientation -#ifdef ROTSPRITE angle_t rollangle; -#endif spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h UINT8 sprite2; // player sprites @@ -402,9 +400,7 @@ typedef struct precipmobj_s // More drawing info: to determine current sprite. angle_t angle; // orientation -#ifdef ROTSPRITE angle_t rollangle; -#endif spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h UINT8 sprite2; // player sprites diff --git a/src/p_saveg.c b/src/p_saveg.c index f96368d0e..85efacf88 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1252,9 +1252,7 @@ typedef enum MD2_SLOPE = 1<<11, #endif MD2_COLORIZED = 1<<12, -#ifdef ROTSPRITE MD2_ROLLANGLE = 1<<13, -#endif } mobj_diff2_t; typedef enum @@ -1474,10 +1472,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) #endif if (mobj->colorized) diff2 |= MD2_COLORIZED; -#ifdef ROTSPRITE if (mobj->rollangle) diff2 |= MD2_ROLLANGLE; -#endif if (diff2 != 0) diff |= MD_MORE; @@ -1642,10 +1638,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) #endif if (diff2 & MD2_COLORIZED) WRITEUINT8(save_p, mobj->colorized); -#ifdef ROTSPRITE if (diff2 & MD2_ROLLANGLE) WRITEANGLE(save_p, mobj->rollangle); -#endif WRITEUINT32(save_p, mobj->mobjnum); } @@ -2722,12 +2716,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) #endif if (diff2 & MD2_COLORIZED) mobj->colorized = READUINT8(save_p); -#ifdef ROTSPRITE if (diff2 & MD2_ROLLANGLE) mobj->rollangle = READANGLE(save_p); - else - mobj->rollangle = 0; -#endif if (diff & MD_REDFLAG) { diff --git a/src/p_setup.c b/src/p_setup.c index 288a483f4..8009eb36e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -664,6 +664,7 @@ static void P_LoadRawSectors(UINT8 *data) ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); ss->lightlevel = SHORT(ms->lightlevel); + ss->spawn_lightlevel = ss->lightlevel; ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); ss->nexttag = ss->firsttag = -1; @@ -2539,8 +2540,7 @@ boolean P_SetupLevel(boolean skipprecip) // chasecam on in chaos, race, coop // chasecam off in match, tag, capture the flag - chase = (gametype == GT_RACE || gametype == GT_COMPETITION || gametype == GT_COOP) - || (maptol & TOL_2D); + chase = (!(gametyperules & GTR_FIRSTPERSON)) || (maptol & TOL_2D); if (!dedicated) { diff --git a/src/p_spec.c b/src/p_spec.c index 614dd4b0a..17a43d5ce 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4692,7 +4692,7 @@ DoneSection2: } case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return - if (player->bot || !G_PlatformGametype()) + if (player->bot || !(gametyperules & GTR_ALLOWEXIT)) break; if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6) { @@ -4727,7 +4727,7 @@ DoneSection2: break; case 3: // Red Team's Base - if (gametype == GT_CTF && P_IsObjectOnGround(player->mo)) + if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo)) { if (player->ctfteam == 1 && (player->gotflag & GF_BLUEFLAG)) { @@ -4760,7 +4760,7 @@ DoneSection2: break; case 4: // Blue Team's Base - if (gametype == GT_CTF && P_IsObjectOnGround(player->mo)) + if ((gametyperules & GTR_TEAMFLAGS) && P_IsObjectOnGround(player->mo)) { if (player->ctfteam == 2 && (player->gotflag & GF_REDFLAG)) { @@ -7224,14 +7224,14 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 308: // Race-only linedef executor. Triggers once. - if (gametype != GT_RACE && gametype != GT_COMPETITION) + if (!(gametyperules & GTR_RACE)) lines[i].special = 0; break; // Linedef executor triggers for CTF teams. case 309: case 311: - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) lines[i].special = 0; break; diff --git a/src/p_user.c b/src/p_user.c index f700588ac..1717a78b9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -387,7 +387,7 @@ UINT8 P_FindLowestMare(void) mobj_t *mo2; UINT8 mare = UINT8_MAX; - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) return 0; // scan the thinkers @@ -638,9 +638,7 @@ static void P_DeNightserizePlayer(player_t *player) player->marebonuslap = 0; player->flyangle = 0; player->anotherflyangle = 0; -#ifdef ROTSPRITE player->mo->rollangle = 0; -#endif P_SetTarget(&player->mo->target, NULL); P_SetTarget(&player->axis1, P_SetTarget(&player->axis2, NULL)); @@ -768,9 +766,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->secondjump = 0; player->flyangle = 0; player->anotherflyangle = 0; -#ifdef ROTSPRITE player->mo->rollangle = 0; -#endif player->powers[pw_shield] = SH_NONE; player->powers[pw_super] = 0; @@ -793,7 +789,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) P_RestoreMusic(player); } - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) { if (player->drillmeter < 48*20) player->drillmeter = 48*20; @@ -2181,7 +2177,7 @@ void P_DoPlayerExit(player_t *player) if (cv_allowexitlevel.value == 0 && !G_PlatformGametype()) return; - else if (gametype == GT_RACE || gametype == GT_COMPETITION) // If in Race Mode, allow + else if (gametyperules & GTR_RACE) // If in Race Mode, allow { if (!countdown) // a 60-second wait ala Sonic 2. countdown = (cv_countdowntime.value - 1)*TICRATE + 1; // Use cv_countdowntime @@ -3110,7 +3106,7 @@ static void P_DoPlayerHeadSigns(player_t *player) } } } - else if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) // If you have the flag (duh). + else if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) // If you have the flag (duh). { // Spawn a got-flag message over the head of the player that // has it (but not on your own screen if you have the flag). @@ -4670,7 +4666,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (player->powers[pw_carry] == CR_BRAKGOOP) player->dashspeed = 0; - if (!((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE)) + if (!((gametyperules & GTR_RACE) && leveltime < 4*TICRATE)) { if (player->dashspeed) { @@ -5048,7 +5044,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { if (onground || player->climbing || player->powers[pw_carry]) ; - else if (gametype == GT_CTF && player->gotflag) + else if ((gametyperules & GTR_TEAMFLAGS) && player->gotflag) ; else if (player->pflags & (PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player has used an ability previously ; @@ -5269,7 +5265,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->secondjump = 0; player->pflags &= ~PF_THOKKED; } - else if (player->pflags & PF_SLIDING || (gametype == GT_CTF && player->gotflag) || player->pflags & PF_SHIELDABILITY) + else if (player->pflags & PF_SLIDING || ((gametyperules & GTR_TEAMFLAGS) && player->gotflag) || player->pflags & PF_SHIELDABILITY) ; /*else if (P_SuperReady(player)) { @@ -5556,7 +5552,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { player->pflags |= PF_JUMPDOWN; - if ((gametype != GT_CTF || !player->gotflag) && !player->exiting) + if ((!(gametyperules & GTR_TEAMFLAGS) || !player->gotflag) && !player->exiting) { if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP) { @@ -6820,7 +6816,6 @@ static void P_DoNiGHTSCapsule(player_t *player) P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); } -#ifdef ROTSPRITE if (!(player->charflags & SF_NONIGHTSROTATION)) { if ((player->mo->state == &states[S_PLAY_NIGHTS_PULL]) @@ -6829,7 +6824,6 @@ static void P_DoNiGHTSCapsule(player_t *player) else player->mo->rollangle = 0; } -#endif if (G_IsSpecialStage(gamemap)) { // In special stages, share rings. Everyone gives up theirs to the capsule player always, because we can't have any individualism here! @@ -7092,9 +7086,7 @@ static void P_NiGHTSMovement(player_t *player) INT32 i; statenum_t flystate; UINT16 visangle; -#ifdef ROTSPRITE angle_t rollangle = 0; -#endif player->pflags &= ~PF_DRILLING; @@ -7133,7 +7125,7 @@ static void P_NiGHTSMovement(player_t *player) && !player->exiting) player->nightstime--; } - else if (gametype != GT_RACE && gametype != GT_COMPETITION + else if (!(gametyperules & GTR_RACE) && !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]) && !(player->capsule && player->capsule->reactiontime) @@ -7279,9 +7271,7 @@ static void P_NiGHTSMovement(player_t *player) && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]) { player->mo->momx = player->mo->momy = player->mo->momz = 0; -#ifdef ROTSPRITE player->mo->rollangle = 0; -#endif return; } @@ -7289,7 +7279,7 @@ static void P_NiGHTSMovement(player_t *player) { player->mo->momx = player->mo->momy = 0; - if (gametype != GT_RACE && gametype != GT_COMPETITION) + if (!(gametyperules & GTR_RACE)) P_SetObjectMomZ(player->mo, FRACUNIT/2, (P_MobjFlip(player->mo)*player->mo->momz >= 0)); else player->mo->momz = 0; @@ -7607,7 +7597,6 @@ static void P_NiGHTSMovement(player_t *player) flystate += (visangle*2); // S_PLAY_NIGHTS_FLY0-C - the *2 is to skip over drill states #endif } -#ifdef ROTSPRITE else { angle_t a = R_PointToAngle(player->mo->x, player->mo->y) - player->mo->angle; @@ -7625,18 +7614,15 @@ static void P_NiGHTSMovement(player_t *player) rollangle = FixedAngle(visangle<mo->state != &states[flystate]) P_SetPlayerMobjState(player->mo, flystate); -#ifdef ROTSPRITE if (player->charflags & SF_NONIGHTSROTATION) player->mo->rollangle = 0; else player->mo->rollangle = rollangle; -#endif if (player == &players[consoleplayer]) localangle = player->mo->angle; @@ -9531,12 +9517,12 @@ static void P_DeathThink(player_t *player) player->playerstate = PST_REBORN; } - if (gametype == GT_RACE || gametype == GT_COMPETITION || (gametype == GT_COOP && (multiplayer || netgame))) + if ((gametyperules & GTR_RACE) || (gametype == GT_COOP && (multiplayer || netgame))) { // Keep time rolling in race mode if (!(countdown2 && !countdown) && !player->exiting && !(player->pflags & PF_GAMETYPEOVER) && !stoppedclock) { - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) { if (leveltime >= 4*TICRATE) player->realtime = leveltime - 4*TICRATE; @@ -9585,6 +9571,7 @@ static void CV_CamRotate2_OnChange(void) static CV_PossibleValue_t CV_CamSpeed[] = {{0, "MIN"}, {1*FRACUNIT, "MAX"}, {0, NULL}}; static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {45, "MAX"}, {0, NULL}}; static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t multiplier_cons_t[] = {{0, "MIN"}, {3*FRACUNIT, "MAX"}, {0, NULL}}; consvar_t cv_cam_dist = {"cam_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_height = {"cam_height", "25", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -9592,6 +9579,7 @@ consvar_t cv_cam_still = {"cam_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_turnmultiplier = {"cam_turnmultiplier", "1.0", CV_FLOAT|CV_SAVE, multiplier_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_orbit = {"cam_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam_adjust = {"cam_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -9600,6 +9588,7 @@ consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam2_turnmultiplier = {"cam2_turnmultiplier", "1.0", CV_FLOAT|CV_SAVE, multiplier_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_orbit = {"cam2_orbit", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_cam2_adjust = {"cam2_adjust", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -10360,6 +10349,11 @@ boolean P_SpectatorJoinGame(player_t *player) else changeto = (P_RandomFixed() & 1) + 1; +#ifdef HAVE_BLUA + if (!LUAh_TeamSwitch(player, changeto, true, false, false)) + return false; +#endif + if (player->mo) { P_RemoveMobj(player->mo); @@ -10371,7 +10365,14 @@ boolean P_SpectatorJoinGame(player_t *player) //Reset away view if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) + { +#ifdef HAVE_BLUA + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUAh_ViewpointSwitch(player, &players[displayplayer], true); +#endif displayplayer = consoleplayer; + } if (changeto == 1) CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[player-players], '\x85', M_GetText("Red team"), '\x80'); @@ -10385,8 +10386,12 @@ boolean P_SpectatorJoinGame(player_t *player) { // Exception for hide and seek. Don't join a game when you simply // respawn in place and sit there for the rest of the round. - if (!(gametype == GT_HIDEANDSEEK && leveltime > (hidetime * TICRATE))) + if (!((gametyperules & GTR_HIDEFROZEN) && leveltime > (hidetime * TICRATE))) { +#ifdef HAVE_BLUA + if (!LUAh_TeamSwitch(player, 3, true, false, false)) + return false; +#endif if (player->mo) { P_RemoveMobj(player->mo); @@ -10409,7 +10414,14 @@ boolean P_SpectatorJoinGame(player_t *player) //Reset away view if (P_IsLocalPlayer(player) && displayplayer != consoleplayer) + { +#ifdef HAVE_BLUA + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUAh_ViewpointSwitch(player, &players[displayplayer], true); +#endif displayplayer = consoleplayer; + } if (gametype != GT_COOP) CONS_Printf(M_GetText("%s entered the game.\n"), player_names[player-players]); @@ -10535,7 +10547,7 @@ void P_DoPityCheck(player_t *player) { // No pity outside of match or CTF. if (player->spectator - || !(gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF)) + || !(gametyperules & GTR_PITYSHIELD)) return; // Apply pity shield if available. @@ -11368,7 +11380,7 @@ void P_PlayerThink(player_t *player) I_Error("player %s is in PST_REBORN\n", sizeu1(playeri)); #endif - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) { INT32 i; @@ -11431,7 +11443,7 @@ void P_PlayerThink(player_t *player) player->exiting > 0 && player->exiting <= 1*TICRATE && (!multiplayer || gametype == GT_COOP ? !mapheaderinfo[gamemap-1]->musinterfadeout : true) && // don't fade if we're fading during intermission. follows Y_StartIntermission intertype = int_coop - (gametype == GT_RACE || gametype == GT_COMPETITION ? countdown2 == 0 : true) && // don't fade on timeout + ((gametyperules & GTR_RACE) ? countdown2 == 0 : true) && // don't fade on timeout player->lives > 0 && // don't fade on game over (competition) P_IsLocalPlayer(player)) { @@ -11546,7 +11558,7 @@ void P_PlayerThink(player_t *player) player->lives = cv_startinglives.value; } - if ((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE) + if ((gametyperules & GTR_RACE) && leveltime < 4*TICRATE) { cmd->buttons &= BT_USE; // Remove all buttons except BT_USE cmd->forwardmove = 0; @@ -11556,7 +11568,7 @@ void P_PlayerThink(player_t *player) // Synchronizes the "real" amount of time spent in the level. if (!player->exiting && !stoppedclock) { - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) { if (leveltime >= 4*TICRATE) player->realtime = leveltime - 4*TICRATE; diff --git a/src/r_main.c b/src/r_main.c index fedc217a4..09bbf6aa1 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1192,6 +1192,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_cam_speed); CV_RegisterVar(&cv_cam_rotate); CV_RegisterVar(&cv_cam_rotspeed); + CV_RegisterVar(&cv_cam_turnmultiplier); CV_RegisterVar(&cv_cam_orbit); CV_RegisterVar(&cv_cam_adjust); @@ -1201,6 +1202,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_cam2_speed); CV_RegisterVar(&cv_cam2_rotate); CV_RegisterVar(&cv_cam2_rotspeed); + CV_RegisterVar(&cv_cam2_turnmultiplier); CV_RegisterVar(&cv_cam2_orbit); CV_RegisterVar(&cv_cam2_adjust); diff --git a/src/r_patch.c b/src/r_patch.c index d4bfa9cbd..0519d6dc9 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -49,8 +49,6 @@ #endif static unsigned char imgbuf[1<<26]; -fixed_t cosang2rad[ROTANGLES]; -fixed_t sinang2rad[ROTANGLES]; // // R_CheckIfPatch @@ -789,11 +787,9 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) size_t sprinfoTokenLength; char *frameChar = NULL; UINT8 frameFrame = 0xFF; -#ifdef ROTSPRITE INT16 frameXPivot = 0; INT16 frameYPivot = 0; rotaxis_t frameRotAxis = 0; -#endif // Sprite identifier sprinfoToken = M_GetToken(NULL); @@ -828,7 +824,6 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) } while (strcmp(sprinfoToken,"}")!=0) { -#ifdef ROTSPRITE if (stricmp(sprinfoToken, "XPIVOT")==0) { Z_Free(sprinfoToken); @@ -852,7 +847,6 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) else if ((stricmp(sprinfoToken, "Z")==0) || (stricmp(sprinfoToken, "ZAXIS")==0) || (stricmp(sprinfoToken, "YAW")==0)) frameRotAxis = ROTAXIS_Z; } -#endif Z_Free(sprinfoToken); sprinfoToken = M_GetToken(NULL); @@ -866,11 +860,9 @@ static void R_ParseSpriteInfoFrame(spriteinfo_t *info) } // set fields -#ifdef ROTSPRITE info->pivot[frameFrame].x = frameXPivot; info->pivot[frameFrame].y = frameYPivot; info->pivot[frameFrame].rotaxis = frameRotAxis; -#endif } // @@ -1093,16 +1085,60 @@ void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) for (i = 0; i < numlumps; i++, lumpinfo++) { name = lumpinfo->name; - // load SPRTINFO lumps - if (!stricmp(name, "SPRTINFO")) + // Load SPRTINFO and SPR_ lumps as SpriteInfo + if (!memcmp(name, "SPRTINFO", 8) || !memcmp(name, "SPR_", 4)) R_ParseSPRTINFOLump(wadnum, i); - // load SPR_ lumps (as DEHACKED lump) - else if (!memcmp(name, "SPR_", 4)) - DEH_LoadDehackedLumpPwad(wadnum, i, false); } } +static UINT16 GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) +{ + fixed_t ofs; + column_t *column; + UINT8 *source; + + if (x >= 0 && x < SHORT(patch->width)) + { + INT32 topdelta, prevdelta = -1; + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[flip ? (patch->width-1-x) : x])); + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (UINT8 *)(column) + 3; + for (ofs = 0; ofs < column->length; ofs++) + { + if ((topdelta + ofs) == y) + return source[ofs]; + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } + + return 0xFF00; +} + #ifdef ROTSPRITE +// +// R_GetRollAngle +// +// Angles precalculated in R_InitSprites. +// +fixed_t rollcosang[ROTANGLES]; +fixed_t rollsinang[ROTANGLES]; +INT32 R_GetRollAngle(angle_t rollangle) +{ + INT32 ra = AngleFixed(rollangle)>>FRACBITS; +#if (ROTANGDIFF > 1) + ra += (ROTANGDIFF/2); +#endif + ra /= ROTANGDIFF; + ra %= ROTANGLES; + return ra; +} + // // R_CacheRotSprite // @@ -1114,8 +1150,8 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp INT32 angle; patch_t *patch; patch_t *newpatch; - UINT16 *rawsrc, *rawdst; - size_t size, size2; + UINT16 *rawdst; + size_t size; INT32 bflip = (flip != 0x00); #define SPRITE_XCENTER (leftoffset) @@ -1160,23 +1196,12 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp leftoffset = width - leftoffset; } - // Draw the sprite to a temporary buffer. - size = (width*height); - rawsrc = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL); - - // can't memset here - for (i = 0; i < size; i++) - rawsrc[i] = 0xFF00; - - R_PatchToFlat_16bpp(patch, rawsrc, bflip); - - // Don't cache angle = 0 for (angle = 1; angle < ROTANGLES; angle++) { INT32 newwidth, newheight; - ca = cosang2rad[angle]; - sa = sinang2rad[angle]; + ca = rollcosang[angle]; + sa = rollsinang[angle]; // Find the dimensions of the rotated patch. { @@ -1237,17 +1262,15 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp #undef BOUNDARYADJUST } - size2 = (newwidth * newheight); - if (!size2) - size2 = size; + // Draw the rotated sprite to a temporary buffer. + size = (newwidth * newheight); + if (!size) + size = (width * height); - rawdst = Z_Malloc(size2 * sizeof(UINT16), PU_STATIC, NULL); - - // can't memset here - for (i = 0; i < size2; i++) + rawdst = Z_Malloc(size * sizeof(UINT16), PU_STATIC, NULL); + for (i = 0; i < size; i++) rawdst[i] = 0xFF00; - // Draw the rotated sprite to a temporary buffer. for (dy = 0; dy < newheight; dy++) { for (dx = 0; dx < newwidth; dx++) @@ -1259,7 +1282,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp sx >>= FRACBITS; sy >>= FRACBITS; if (sx >= 0 && sy >= 0 && sx < width && sy < height) - rawdst[(dy*newwidth)+dx] = rawsrc[(sy*width)+sx]; + rawdst[(dy*newwidth)+dx] = GetPatchPixel(patch, sx, sy, bflip); } } @@ -1296,7 +1319,6 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp sprframe->rotsprite.cached[rot] = true; // free image data - Z_Free(rawsrc); Z_Free(patch); } #undef SPRITE_XCENTER diff --git a/src/r_patch.h b/src/r_patch.h index 8a8ab5602..72371f253 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -18,7 +18,6 @@ #include "doomdef.h" // Structs -#ifdef ROTSPRITE typedef enum { ROTAXIS_X, // Roll (the default) @@ -31,13 +30,10 @@ typedef struct INT32 x, y; rotaxis_t rotaxis; } spriteframepivot_t; -#endif typedef struct { -#ifdef ROTSPRITE spriteframepivot_t pivot[64]; -#endif boolean available; } spriteinfo_t; @@ -66,11 +62,12 @@ void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); // Sprite rotation #ifdef ROTSPRITE +INT32 R_GetRollAngle(angle_t rollangle); void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip); void R_FreeSingleRotSprite(spritedef_t *spritedef); void R_FreeSkinRotSprite(size_t skinnum); -extern fixed_t cosang2rad[ROTANGLES]; -extern fixed_t sinang2rad[ROTANGLES]; +extern fixed_t rollcosang[ROTANGLES]; +extern fixed_t rollsinang[ROTANGLES]; #endif #endif // __R_PATCH__ diff --git a/src/r_things.c b/src/r_things.c index aa2a73515..cd7e40064 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -500,7 +500,7 @@ void R_InitSprites(void) { size_t i; #ifdef ROTSPRITE - INT32 angle, realangle = 0; + INT32 angle; float fa; #endif @@ -508,12 +508,11 @@ void R_InitSprites(void) negonearray[i] = -1; #ifdef ROTSPRITE - for (angle = 0; angle < ROTANGLES; angle++) + for (angle = 1; angle < ROTANGLES; angle++) { - fa = ANG2RAD(FixedAngle(realangle<rollangle; - UINT32 rollangle = AngleFixed(arollangle)>>FRACBITS; + INT32 rollangle = 0; #endif #ifndef PROPERPAPER @@ -1260,11 +1258,11 @@ static void R_ProjectSprite(mobj_t *thing) spr_topoffset = spritecachedinfo[lump].topoffset; #ifdef ROTSPRITE - if (rollangle > 0) + if (thing->rollangle) { + rollangle = R_GetRollAngle(thing->rollangle); if (!sprframe->rotsprite.cached[rot]) R_CacheRotSprite(thing->sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip); - rollangle /= ROTANGDIFF; rotsprite = sprframe->rotsprite.patch[rot][rollangle]; if (rotsprite != NULL) { @@ -2839,7 +2837,7 @@ boolean R_SkinUsable(INT32 playernum, INT32 skinnum) { return ((skinnum == -1) // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... || (!skins[skinnum].availability) - || ((playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) + || (((netgame || multiplayer) && playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) || (modeattacking) // If you have someone else's run you might as well take a look || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. || (netgame && (cv_forceskin.value == skinnum)) // Force 2. diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index d0830396f..5d0009927 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -20,12 +20,17 @@ #include "../doomdef.h" #include "../m_argv.h" #include "../d_main.h" +#include "../m_misc.h"/* path shit */ #include "../i_system.h" -#ifdef __GNUC__ +#if defined (__GNUC__) || defined (__unix__) #include #endif +#ifdef __unix__ +#include +#endif + #include "time.h" // For log timestamps #ifdef HAVE_SDL @@ -47,7 +52,7 @@ extern int SDL_main(int argc, char *argv[]); #ifdef LOGMESSAGES FILE *logstream = NULL; -char logfilename[1024]; +char logfilename[1024]; #endif #ifndef DOXYGEN @@ -133,34 +138,86 @@ int main(int argc, char **argv) { time_t my_time; struct tm * timeinfo; - char buf[26]; + const char *format; + const char *reldir; + int left; + boolean fileabs; +#ifdef __unix__ + const char *link; +#endif logdir = D_Home(); my_time = time(NULL); timeinfo = localtime(&my_time); - strftime(buf, 26, "%Y-%m-%d %H-%M-%S", timeinfo); - strcpy(logfilename, va("log-%s.txt", buf)); - -#ifdef DEFAULTDIR - if (logdir) + if (M_CheckParm("-logfile") && M_IsNextParm()) { - // Create dirs here because D_SRB2Main() is too late. - I_mkdir(va("%s%s"DEFAULTDIR, logdir, PATHSEP), 0755); - I_mkdir(va("%s%s"DEFAULTDIR"%slogs",logdir, PATHSEP, PATHSEP), 0755); - strcpy(logfilename, va("%s%s"DEFAULTDIR"%slogs%s%s",logdir, PATHSEP, PATHSEP, PATHSEP, logfilename)); + format = M_GetNextParm(); + fileabs = M_IsPathAbsolute(format); } else -#endif { - I_mkdir("."PATHSEP"logs"PATHSEP, 0755); - strcpy(logfilename, va("."PATHSEP"logs"PATHSEP"%s", logfilename)); + format = "log-%Y-%m-%d_%H-%M-%S.txt"; + fileabs = false; } - logstream = fopen(logfilename, "wt"); + if (fileabs) + { + strftime(logfilename, sizeof logfilename, format, timeinfo); + } + else + { + if (M_CheckParm("-logdir") && M_IsNextParm()) + reldir = M_GetNextParm(); + else + reldir = "logs"; + + if (M_IsPathAbsolute(reldir)) + { + left = snprintf(logfilename, sizeof logfilename, + "%s"PATHSEP, reldir); + } + else +#ifdef DEFAULTDIR + if (logdir) + { + left = snprintf(logfilename, sizeof logfilename, + "%s"PATHSEP DEFAULTDIR PATHSEP"%s"PATHSEP, logdir, reldir); + } + else +#endif/*DEFAULTDIR*/ + { + left = snprintf(logfilename, sizeof logfilename, + "."PATHSEP"%s"PATHSEP, reldir); + } +#endif/*LOGMESSAGES*/ + + strftime(&logfilename[left], sizeof logfilename - left, + format, timeinfo); + } + + M_MkdirEachUntil(logfilename, + M_PathParts(logdir) - 1, + M_PathParts(logfilename) - 1, 0755); + +#ifdef __unix__ + logstream = fopen(logfilename, "w"); +#ifdef DEFAULTDIR + if (logdir) + link = va("%s/"DEFAULTDIR"/latest-log.txt", logdir); + else +#endif/*DEFAULTDIR*/ + link = "latest-log.txt"; + unlink(link); + if (symlink(logfilename, link) == -1) + { + I_OutputMsg("Error symlinking latest-log.txt: %s\n", strerror(errno)); + } +#else/*__unix__*/ + logstream = fopen("latest-log.txt", "wt+"); +#endif/*__unix__*/ } -#endif //I_OutputMsg("I_StartupSystem() ...\n"); I_StartupSystem(); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 52186baae..81420e757 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2484,6 +2484,48 @@ void I_RemoveExitFunc(void (*func)()) } } +#ifndef __unix__ +static void Shittycopyerror(const char *name) +{ + I_OutputMsg( + "Error copying log file: %s: %s\n", + name, + strerror(errno) + ); +} + +static void Shittylogcopy(void) +{ + char buf[8192]; + FILE *fp; + size_t r; + if (fseek(logstream, 0, SEEK_SET) == -1) + { + Shittycopyerror("fseek"); + } + else if (( fp = fopen(logfilename, "wt") )) + { + while (( r = fread(buf, 1, sizeof buf, logstream) )) + { + if (fwrite(buf, 1, r, fp) < r) + { + Shittycopyerror("fwrite"); + break; + } + } + if (ferror(logstream)) + { + Shittycopyerror("fread"); + } + fclose(fp); + } + else + { + Shittycopyerror(logfilename); + } +} +#endif/*__unix__*/ + // // Closes down everything. This includes restoring the initial // palette and video mode, and removing whatever mouse, keyboard, and @@ -2506,6 +2548,9 @@ void I_ShutdownSystem(void) if (logstream) { I_OutputMsg("I_ShutdownSystem(): end of logstream.\n"); +#ifndef __unix__ + Shittylogcopy(); +#endif fclose(logstream); logstream = NULL; } diff --git a/src/st_stuff.c b/src/st_stuff.c index 963dc24cc..5e05030c3 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -694,7 +694,7 @@ static void ST_drawTime(void) else { // Counting down the hidetime? - if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (stplyr->realtime <= (hidetime*TICRATE))) + if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime <= (hidetime*TICRATE))) { tics = (hidetime*TICRATE - stplyr->realtime); if (tics < 3*TICRATE) @@ -705,11 +705,11 @@ static void ST_drawTime(void) else { // Hidetime finish! - if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (stplyr->realtime < ((hidetime+1)*TICRATE))) + if ((gametyperules & GTR_HIDETIME) && (stplyr->realtime < ((hidetime+1)*TICRATE))) ST_drawRaceNum(hidetime*TICRATE - stplyr->realtime); // Time limit? - if (gametype != GT_COOP && gametype != GT_RACE && gametype != GT_COMPETITION && cv_timelimit.value && timelimitintics > 0) + if ((gametyperules & GTR_TIMELIMIT) && cv_timelimit.value && timelimitintics > 0) { if (timelimitintics > stplyr->realtime) { @@ -723,7 +723,7 @@ static void ST_drawTime(void) downwards = true; } // Post-hidetime normal. - else if (gametype == GT_TAG || gametype == GT_HIDEANDSEEK) + else if (gametyperules & GTR_TAG) tics = stplyr->realtime - hidetime*TICRATE; // "Shadow! What are you doing? Hurry and get back here // right now before the island blows up with you on it!" @@ -912,7 +912,7 @@ static void ST_drawLivesArea(void) else if (stplyr->spectator) v_colmap = V_GRAYMAP; // Tag - else if (gametype == GT_TAG || gametype == GT_HIDEANDSEEK) + else if (gametyperules & GTR_TAG) { if (stplyr->pflags & PF_TAGIT) { @@ -1228,6 +1228,9 @@ void ST_startTitleCard(void) // void ST_preDrawTitleCard(void) { + if (!G_IsTitleCardAvailable()) + return; + if (lt_ticker >= (lt_endtime + TICRATE)) return; @@ -1243,6 +1246,9 @@ void ST_preDrawTitleCard(void) // void ST_runTitleCard(void) { + if (!G_IsTitleCardAvailable()) + return; + if (lt_ticker >= (lt_endtime + TICRATE)) return; @@ -1296,6 +1302,9 @@ void ST_drawTitleCard(void) INT32 zzticker; patch_t *actpat, *zigzag, *zztext; + if (!G_IsTitleCardAvailable()) + return; + #ifdef HAVE_BLUA if (!LUA_HudEnabled(hud_stagetitle)) goto luahook; @@ -1774,7 +1783,7 @@ static void ST_drawNiGHTSHUD(void) ST_drawNiGHTSLink(); } - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) { ST_drawScore(); ST_drawTime(); @@ -2215,34 +2224,37 @@ static void ST_drawTextHUD(void) if (G_IsSpecialStage(gamemap)) textHUDdraw(M_GetText("\x82""Wait for the stage to end...")) - else if (gametype == GT_COOP) + else if (G_PlatformGametype()) { - if (stplyr->lives <= 0 - && cv_cooplives.value == 2 - && (netgame || multiplayer)) + if (gametype == GT_COOP) { - INT32 i; - for (i = 0; i < MAXPLAYERS; i++) + if (stplyr->lives <= 0 + && cv_cooplives.value == 2 + && (netgame || multiplayer)) { - if (!playeringame[i]) - continue; + INT32 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; - if (&players[i] == stplyr) - continue; + if (&players[i] == stplyr) + continue; - if (players[i].lives > 1) - break; - } + if (players[i].lives > 1) + break; + } - if (i != MAXPLAYERS) - textHUDdraw(M_GetText("You'll steal a life on respawn...")) + if (i != MAXPLAYERS) + textHUDdraw(M_GetText("You'll steal a life on respawn...")) + else + textHUDdraw(M_GetText("Wait to respawn...")) + } else textHUDdraw(M_GetText("Wait to respawn...")) } - else - textHUDdraw(M_GetText("Wait to respawn...")) } - else + else if (G_GametypeHasSpectators()) textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) } @@ -2285,13 +2297,14 @@ static void ST_drawTextHUD(void) } } } - else if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator)) + else if ((gametyperules & GTR_TAG) && (!stplyr->spectator)) { if (leveltime < hidetime * TICRATE) { if (stplyr->pflags & PF_TAGIT) { - textHUDdraw(M_GetText("\x82""You are blindfolded!")) + if (gametyperules & GTR_BLINDFOLDED) + textHUDdraw(M_GetText("\x82""You are blindfolded!")) textHUDdraw(M_GetText("Waiting for players to hide...")) } else if (gametype == GT_HIDEANDSEEK) @@ -2306,7 +2319,8 @@ static void ST_drawTextHUD(void) textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) donef12 = true; } - textHUDdraw(M_GetText("You cannot move while hiding.")) + if (gametyperules & GTR_HIDEFROZEN) + textHUDdraw(M_GetText("You cannot move while hiding.")) } } @@ -2328,27 +2342,27 @@ static void ST_drawTeamHUD(void) if (F_GetPromptHideHud(0)) // y base is 0 return; - if (gametype == GT_CTF) + if (gametyperules & GTR_TEAMFLAGS) p = bflagico; else p = bmatcico; - + #ifdef HAVE_BLUA if (LUA_HudEnabled(hud_teamscores)) #endif V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); - - if (gametype == GT_CTF) + + if (gametyperules & GTR_TEAMFLAGS) p = rflagico; else p = rmatcico; - + #ifdef HAVE_BLUA if (LUA_HudEnabled(hud_teamscores)) #endif V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p); - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMFLAGS)) goto num; { INT32 i; @@ -2676,7 +2690,7 @@ static void ST_overlayDrawer(void) } // If you are in overtime, put a big honkin' flashin' message on the screen. - if (G_RingSlingerGametype() && cv_overtime.value + if (((gametyperules & GTR_TIMELIMIT) && (gametyperules & GTR_OVERTIME)) && cv_overtime.value && (leveltime > (timelimitintics + TICRATE/2)) && cv_timelimit.value && (leveltime/TICRATE % 2 == 0)) V_DrawCenteredString(BASEVIDWIDTH/2, 184, V_PERPLAYER, M_GetText("OVERTIME!")); @@ -2691,7 +2705,7 @@ static void ST_overlayDrawer(void) ST_drawMatchHUD(); // Race HUD Stuff - if (gametype == GT_RACE || gametype == GT_COMPETITION) + if (gametyperules & GTR_RACE) ST_drawRaceHUD(); // Emerald Hunt Indicators @@ -2796,7 +2810,7 @@ void ST_Drawer(void) if (rendermode != render_none) ST_doPaletteStuff(); // Blindfold! - if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) + if ((gametyperules & GTR_BLINDFOLDED) && (leveltime < hidetime * TICRATE)) { if (players[displayplayer].pflags & PF_TAGIT) diff --git a/src/y_inter.c b/src/y_inter.c index 842bd1b28..b26c0797e 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -37,6 +37,10 @@ #include "m_cond.h" // condition sets #include "lua_hook.h" // IntermissionThinker hook +#ifdef HAVE_BLUA +#include "lua_hud.h" +#endif + #ifdef HWRENDER #include "hardware/hw_main.h" #endif @@ -164,6 +168,7 @@ static INT32 tallydonetic = -1; static INT32 endtic = -1; intertype_t intertype = int_none; +intertype_t intermissiontypes[NUMGAMETYPES]; static void Y_RescaleScreenBuffer(void); static void Y_AwardCoopBonuses(void); @@ -318,9 +323,17 @@ void Y_IntermissionDrawer(void) // Bonus loops INT32 i; - if (intertype == int_none || rendermode == render_none) + if (rendermode == render_none) return; + if (intertype == int_none) + { +#ifdef HAVE_BLUA + LUAh_IntermissionHUD(); +#endif + return; + } + if (!usebuffer) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); @@ -358,6 +371,12 @@ void Y_IntermissionDrawer(void) else V_DrawPatchFill(bgtile); +#ifdef HAVE_BLUA + LUAh_IntermissionHUD(); + if (!LUA_HudEnabled(hud_intermissiontally)) + goto skiptallydrawer; +#endif + if (intertype == int_coop) { INT32 bonusy; @@ -907,6 +926,12 @@ void Y_IntermissionDrawer(void) } } +#ifdef HAVE_BLUA +skiptallydrawer: + if (!LUA_HudEnabled(hud_intermissionmessages)) + return; +#endif + if (timer) V_DrawCenteredString(BASEVIDWIDTH/2, 188, V_YELLOWMAP, va("start in %d seconds", timer/TICRATE)); @@ -1187,7 +1212,9 @@ void Y_StartIntermission(void) timer = 1; } - if (gametype == GT_COOP) + if (intermissiontypes[gametype] != int_none) + intertype = intermissiontypes[gametype]; + else if (gametype == GT_COOP) intertype = (G_IsSpecialStage(gamemap)) ? int_spec : int_coop; else if (gametype == GT_TEAMMATCH) intertype = int_teammatch; diff --git a/src/y_inter.h b/src/y_inter.h index 7dffbff32..5cf2cc1b8 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -31,3 +31,4 @@ typedef enum int_comp, // Competition } intertype_t; extern intertype_t intertype; +extern intertype_t intermissiontypes[NUMGAMETYPES];