From f2cdf34c98ebdb2e5a17aeb549212b6a2eb3f1b6 Mon Sep 17 00:00:00 2001 From: Marisa Kirisame Date: Fri, 6 Sep 2019 00:20:14 +0200 Subject: [PATCH] Current commit does not run and I don't know why. Sentry partially implemented. Motion Detector implemented. Light/Dark Flares implemented. --- ItemLore.md | 29 +- Readme.md | 14 +- gldefs.txt | 53 +++- graphics/DetHud.png | Bin 0 -> 2075 bytes graphics/DetSpot0.png | Bin 0 -> 147 bytes graphics/DetSpot1.png | Bin 0 -> 160 bytes keyconf.txt | 4 + language.txt | 25 +- modeldef.umisc | 59 +++- models/LightFlareM_a.3d | Bin 4204 -> 4204 bytes sndinfo.txt | 9 + zscript/biggun.zsc | 2 +- zscript/miscitems.zsc | 569 +++++++++++++++++++++++++++++++++++++- zscript/ueightball.zsc | 4 +- zscript/unrealcommon.zsc | 5 + zscript/unrealhud.zsc | 4 +- zscript/upowerups.zsc | 106 ++++++- zscript/utranslocator.zsc | 2 +- 18 files changed, 835 insertions(+), 50 deletions(-) create mode 100644 graphics/DetHud.png create mode 100644 graphics/DetSpot0.png create mode 100644 graphics/DetSpot1.png create mode 100644 keyconf.txt diff --git a/ItemLore.md b/ItemLore.md index 67007da..b6f5904 100644 --- a/ItemLore.md +++ b/ItemLore.md @@ -14,10 +14,13 @@ this item isn't really given to players. It may get use if I or someone else recreate Unreal 1 maps. This mod's version of the Translator has additional features: -- Vertical scrolling for long messages, just use the up/down arrow keys -- Toggling hint display, press page down if there's a glowing icon on the - bottom right. Press page up to return to the message. -- Going through previous messages, by pressing left / right. +- Vertical scrolling for long messages, just use the up/down arrow keys, + mouse wheel or drag along the bar. +- Toggling hint display, if there's a glowing icon on the bottom right, press + page down or click on it. Press page up / click on the bottom left to return + to the message. +- Going through previous messages, by pressing left / right or clicking the + arrows next to the page numbers. ## Amplifier @@ -28,7 +31,8 @@ When active, dramatically enhances the power of the Dispersion Pistol and ASMD. Deadens the sound of emitted from your weapons, making it much easier to launch sneak attacks. -In the original game this item was pretty much useless, but here it works. +This item was pretty much useless in the original game, but here it really does +have a considerable effect. ## Flare @@ -67,17 +71,16 @@ Activating the boots enables you to jump much higher than normal. Once picked up the Boots only last for a short period of time, so take advantage of them while you can. -In addition, the boots can provide resistance to damaging floors. +In addition, the Boots can provide resistance to damaging floors. ## Scuba Gear -Gives you the ability to breathe while underwater. - -Lasts around 2 minutes. +Gives you the ability to breathe while underwater. Lasts around 2 minutes. ## Searchlight -Functions like a flashlight, but has a nearly inexhaustible power supply. +Provides considerably more light than a flashlight and has around half an hour +of battery life. Definitely worth keeping around. ## Nali Fruit Seed @@ -87,10 +90,8 @@ is fully grown, your health gain will be less substantial. ## Voice Box -Creates a sound diversion to distract your enemies. - -In the original this had no effect, but here enemies will actually be alerted -by voice boxes, and will attempt to get rid of the annoying noise. +Creates a sound diversion to distract your enemies, so you can make your +escape while they attempt to get rid of the annoying noise this device emits. ## Bandages diff --git a/Readme.md b/Readme.md index 634265b..1392b9d 100644 --- a/Readme.md +++ b/Readme.md @@ -16,6 +16,7 @@ Doom Tournament (currently the devel branch is required). - Eightball (slot 5) (replaces rocket launcher) - Single rocket mode for Eightball - Flak Cannon (slot 6) (replaces rocket launcher) + - SMP 7243 (slot 0) (replaces bfg9000) - Backpack (replaces backpack, identical to Doom Tournament version) - Unreal 1 HUD - Translator (has to be spawned in, since it would only be useful for mappers) @@ -41,6 +42,8 @@ Doom Tournament (currently the devel branch is required). - Searchlight (must be placed manually for balance reasons) - Jump Boots (replaces radsuit) - SCUBA Gear (replaces radsuit if map has swimmable water) + - Motion Detector (replaces computer map) + - Light & Dark Flares ## In progress @@ -48,7 +51,8 @@ Doom Tournament (currently the devel branch is required). - GES Bio Rifle (slot 8) (replaces plasma rifle) - Rifle (slot 9) (replaces plasma rifle) - Minigun (slot 0) (replaces chaingun) - - SMP 7243 (slot 0) (replaces bfg9000) + + - Minigun Sentry (rare spawn in backpacks) ## Planned @@ -65,7 +69,7 @@ Doom Tournament (currently the devel branch is required). - Stunner (slot 4) (replaces chainsaw) - Razorclaw (slot 1) (replaces chainsaw) - - Teleport Capsules (slot 9) + - Teleport Capsules (slot 1) - Protomag (slot 2) (replaces pistol) - Dual Protomags - Quadshot (slot 3) (replaces shotguns) @@ -73,13 +77,9 @@ Doom Tournament (currently the devel branch is required). - Impaler (slot 7) (replaces plasma rifle) - Flamethrower (slot 6) (replaces plasma rifle) - Fireblaster (slot 5) (replaces rocket launcher) - - Demolisher (slot 0) (replaces bfg9000) + - Demolisher (slot 9) (replaces bfg9000) - Autocannon (slot 0) (replaces bfg9000) - - Motion Detector (replaces computer map) - - Light & Dark Flares - - Minigun Sentry (rare spawn in backpacks) - ## Known bugs - N/A diff --git a/gldefs.txt b/gldefs.txt index eabc7cc..c2735f1 100644 --- a/gldefs.txt +++ b/gldefs.txt @@ -224,13 +224,31 @@ FlickerLight2 FLARELIGHT Size 112 SecondarySize 120 Interval 0.1 - Offset 6 0 1 + Offset 0 1 6 } Object FlareThrownX { frame "FLAR" { light "FLARELIGHT" } } +FlickerLight2 LIGHTFLARE +{ + Color 1.0 1.0 1.0 + Size 112 + SecondarySize 120 + Interval 0.1 + Offset 0 1 6 +} +FlickerLight2 DARKFLARE +{ + Color 0.6 0.6 0.6 + Size 112 + SecondarySize 120 + Interval 0.1 + Subtractive 1 + Offset 0 1 6 +} + FlickerLight2 DAMMOLIGHT1 { Color 0.2 0.2 1.0 @@ -299,6 +317,39 @@ Object AsmdBall Frame "TAZB" { light "ASMDBALLLIGHT" } } +FlickerLight2 SENTRYLIGHT1 +{ + Color 1.0 0.6 0.0 + Size 80 + SecondarySize 96 + Interval 0.1 + Offset 0 4 15 +} +FlickerLight2 SENTRYLIGHT2 +{ + Color 0.4 0.2 0.0 + Size 80 + SecondarySize 96 + Interval 0.1 + Offset 0 4 15 +} + +Object MinigunSentry +{ + Frame "SENFA" { light "SENTRYLIGHT1" } + Frame "SENFB" { light "SENTRYLIGHT2" } + Frame "SENFD" { light "SENTRYLIGHT1" } + Frame "SENFE" { light "SENTRYLIGHT2" } + Frame "SENFG" { light "SENTRYLIGHT1" } + Frame "SENFH" { light "SENTRYLIGHT2" } + Frame "SENFJ" { light "SENTRYLIGHT1" } + Frame "SENFK" { light "SENTRYLIGHT2" } + Frame "SENFM" { light "SENTRYLIGHT1" } + Frame "SENFN" { light "SENTRYLIGHT2" } + Frame "SENFP" { light "SENTRYLIGHT1" } + Frame "SENFQ" { light "SENTRYLIGHT2" } +} + // Shaders / Brightmaps HardwareShader Texture "graphics/MenuBarr.png" { diff --git a/graphics/DetHud.png b/graphics/DetHud.png new file mode 100644 index 0000000000000000000000000000000000000000..b0a8c086b6d3a3d7c20ee4f3946951610a88ae6c GIT binary patch literal 2075 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4rT@hhO2JvTnr4%3;{kNt_+L}3IZ$=LR=EU zJaR&8k|Mm)qU=(leDWe3GNK%^Vq6NM+=^nnauPhs;%rLdd@2$g@{;^&lFX`-oC;C` zs*+qPl7foTf@)Gcs!~E)lDtYXLh91IDl)uk(!$Cz!rD@NnlkJvvV58{9LlmH8Zvyk z(j2OC{93Y{nzH*a)Rm#g6axFY6@c7@IexI;zq}D#E&I5{9Z0#;PJlsuC6|{CesVCTb$)s-nhfk_H+g`WliZ z>Y|1kq6QjLW*UN~8e)c;(xw{H_G-drn&QS<;znB1rkXMqn!@Iq5@wn*#@aHLTEaG( zA{JT_mfDggx^l+4%BH&V);gkAI#QN8^5%Nd*1FQ>`U9Rwt6y_1~L`~igx-E zw)(PGhO$nE4E6?+b_Q}z`f^T&9M1ak)<$ynhVsrvoYuzjE=F8d#>zIv@{UH*4n_*j z#)2-!f=Zbk#xi!MicThqE+(?hCQ2@*${r@l4(7`C<{GYMDvlN^?&eZ%=JIal zs$OPlE|${n77EUms_qu5-sWmvmSP^3ir$vuE>>z@ma-m}YVOwJZq_oMR!Ux0%AQsl zzLpvuHWIEj8a~!?-qtE!)|!4+ntnDS?zYNqwi>~fS^?Io0k(Yp)>?tqs{Xd39(F1L z*4plNn!dKGK{je$_6h-ZVu3c=p7yF9_F7){YT?%Ees*fXw(3E)I{x@J=0e9*y%-o+u6epRhGg8kIy2EHI#s02 ze^Gbx-Q4AoQNfqOjHJS2tJA|5nrHi*U2}= zUGBY@;%_3g>a*+R?fGf?UymfK2XE{Rt=g!t|G(y`gzc6J(|*5xc>ne5)h|P=zDDOM zl}_xGw+#t&jO3SjwR7K=egB?c`s4Czcl7pky}k3^WYFSGvSUkiPAIdaMFC0WV6 z_fzlezWpfQAiLa7SNtREo#%yijvAqSFV0#rycL`p?yQr0nEAvi+XH8^J~Fgu9{S59 zB$)8Qp(F4SBUcwsL0(wjjg*aIZQ@rd7&KiEb%t_%6q(5OB1+r6#x=@z&*#;mA4N`P zR($7Da!|Q^c<0mRj)o-Zl)8KumKSdfJ{{=eSh1D)vvM!{ge|`kKI~%UcW`f0EN0)x zZl=ch{P~@Z1`g(6OMAHkGUpFGk=2(wV0p+XhifDIy^B08#vQZXoZWQ6EbkEWj?Lc{ zCQMLb^4lojqmWgUn=b!@-TMQ>uU`g7o(asId*sy2`<+!s>VwbSg=1-% ze)WUD-W|&`yzkxgRkq%}dB(YSk>_rfu1&PEHsy`g?l{+Xqo9l}CjELT>qd6zb9thH z{4PhoPKb00F;RN|=9<9V*u<&A=gzYmEyX)OJk;V*S4mW89~x1V)4!_7jBe`vPsf~`{C->K@;EiS=?4FbS$BBO@LriB z+4MtVncDPyd>6YrmUk>SDAN3Fc_e&`GrRNVj!BwNO@1CJVtu4}>O8;Pf~-%<9y8_R zbdO$r;vasdgP~P&U!;qV#UdlW$>LdpjArHrI!ULd$UHWg>FPVvdBV=#nMRUNrp%l# zzv0H`<~OlNel}LOw7%m>;+H%5M`6OjIr1C6KQMUpN1@Zkena{9hgQ~mZF%0ViTftu zuOjr3%S_N_p^tO6iId{OEiZh{b}wmopv4ld*dnC5Hjsnc{NuLnc~7q8J>={*O`Rnq z{C82ujal)oHXrBzeYdZUW0M(kq~GPN)~-uofm&02oT8*=*R0!iEveqGX~Bci$Vsos3;8?P4ry~nbH z`7Psi^MvcK=idA0lAoesdD73%=*%#GF5$ihgu_*InLP z#`f!XmGbgQ)9vN^_sQCvsZG}_X0vbP0l+XkKKj9}Q literal 0 HcmV?d00001 diff --git a/graphics/DetSpot1.png b/graphics/DetSpot1.png new file mode 100644 index 0000000000000000000000000000000000000000..9116401e955e997d828689754ae84d97c31879fd GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7IMRz8lRz{G?-5@&m4ShQ zv%n*=n1O*?7=#%aX3ddcU|_KGba4!^=uJ+LV6AYpW2UZ3KgAc+tb@*<3FfcGMc)I$ztaD0e F0sw=)EtdcQ literal 0 HcmV?d00001 diff --git a/keyconf.txt b/keyconf.txt new file mode 100644 index 0000000..e6a8326 --- /dev/null +++ b/keyconf.txt @@ -0,0 +1,4 @@ +addkeysection "$STING_KEYS" Doomreal +addmenukey "$STING_USETRANS" usetrans +alias usetrans "netevent usetranslator" +defaultbind F2 usetrans diff --git a/language.txt b/language.txt index c24da94..b9edf67 100644 --- a/language.txt +++ b/language.txt @@ -32,7 +32,8 @@ O_FLAMEGUN = "%o was charred by %k's Fireblaster."; O_FLAMETHROWER = "%o was thoroughly roasted by %k's Flamethrower."; O_BIGGUN = "%k blew a hole through %o with the Demolisher."; O_SMINI = "%o got blasted into steaming chunks by %k's Autocannon."; -O_SENTRY = "%o shouldn't have walked into the sights of %k's Sentry."; +O_SENTRY = "%%o shouldn't have walked into the sights of %s."; +O_OWNSENTRY = "%o was gunned down by %p own Sentry."; O_STINGERX = "%o ate flaming Tarydium death thanks to %k."; O_OLSMP = "%o didn't stand a chance against %k's SMP 7243."; /* Pickup messages */ @@ -137,6 +138,7 @@ T_FLAMETHROWER = "Flamethrower"; T_BIGGUN = "Demolisher"; T_SMINI = "Autocannon"; T_SENTRY = "Sentry"; +T_OWNEDSENTRY = "%s's Sentry"; T_TRANSLATOR = "Translator"; T_UARMOR = "Assault Vest"; T_KEVSUIT = "Kevlar Suit"; @@ -178,6 +180,13 @@ D_POWERSHIELD = "The Power Shield has depleted."; D_DAMPENER = "Acoustic Dampener has run out."; D_AMPLIFIER = "Energy Amplifier is out of power."; D_SCUBA = "SCUBA Gear oxygen supply has run out."; +D_FLASHLIGHT = "The Flashlight batteries have died."; +D_SEARCHLIGHT = "The Searchlight has run out of battery."; +D_DETECTOR = "The Detector has run out of battery."; +M_SENTRYDOWN = "Your Sentry has been destroyed."; +M_SENTRYDRY = "Your Sentry has run out of ammo."; +M_SENTRYHIJACK = "Your Sentry has been hijacked."; +M_MSNOROOM = "No room to deploy Sentry."; M_FFNOROOM = "No room to activate Force Field."; S_MINHUD = "Health %d Score %d Ammo %d"; S_MINHUD2 = "Health %d Score %d Ammo %d/%d"; @@ -227,6 +236,8 @@ STING_CMUS = "Music:"; STING_CSND = "Sound Effects:"; STING_CGT = "Producer for GT:"; STING_CBIZ = "Biz:"; +STING_KEYS = "Doomreal"; +STING_USETRANS = "Use Translator"; [es esm esn esg esc esa esd esv eso esr ess esf esl esy esz esb ese esh esi esu] /* Obituaries */ @@ -251,7 +262,8 @@ O_FLAMEGUN = "%o fue carbonizad@[ao_esp] por el Bláster de Fuego de %k."; O_FLAMETHROWER = "%o fue asad@[ao_esp] a conciencia por el Lanzallamas de %k."; O_BIGGUN = "%k abrió un hoyo a través de %o con el Demoledor."; O_SMINI = "%o fue reventad@[ao_esp] en pedazos humeantes por el Autocañón de %k."; -O_SENTRY = "%o no debería haberse metido en el punto de mira de la Torreta de %k."; +O_SENTRY = "%%o no debería haberse metido en el punto de mira de la %s."; +O_OWNSENTRY = "%o fue abatid@[ao_esp] por su propi@[ao_esp] Torreta."; O_STINGERX = "%o tragó muerte ardiente de Tarydium gracias a %k."; O_OLSMP = "%o no tenía ninguna oportunidad contra el SMP 7243 de %k."; /* Pickup messages */ @@ -352,6 +364,7 @@ T_FLAMETHROWER = "Lanzallamas"; T_BIGGUN = "Demoledor"; T_SMINI = "Autocañón"; T_SENTRY = "Torreta"; +T_OWNEDSENTRY = "Torreta de %s"; T_TRANSLATOR = "Traductor"; T_UARMOR = "Coraza de Asalto"; T_KEVSUIT = "Traje de Kevlar"; @@ -383,6 +396,13 @@ D_POWERSHIELD = "El Escudo de Fuerza se ha agotado."; D_DAMPENER = "El Amortiguador Acústico se ha agotado."; D_AMPLIFIER = "El Amplificador de Energía se ha agotado."; D_SCUBA = "La reserva de oxígeno del Kit de Buceo se ha agotado."; +D_FLASHLIGHT = "Las pilas de la Linterna se han agotado."; +D_SEARCHLIGHT = "El Faro se ha quedado sin energía."; +D_DETECTOR = "El Detector se ha quedado sin energía."; +M_SENTRYDOWN = "Tu Torreta ha sido destruida."; +M_SENTRYDRY = "Tu Torreta se ha quedado sin munición."; +M_SENTRYHIJACK = "Tu Torreta ha sido hackeada."; +M_MSNOROOM = "No hay espacio para colocar la Torreta."; M_FFNOROOM = "No hay espacio para activar el Campo de Fuerza."; S_MINHUD = "Salud %d Puntuación %d Munición %d"; S_MINHUD2 = "Salud %d Puntuación %d Munición %d/%d"; @@ -428,6 +448,7 @@ STING_CMUS = "Música:"; STING_CSND = "Efectos de Sonido:"; STING_CGT = "Productor para GT:"; STING_CBIZ = "Negocios:"; +STING_USETRANS = "Usar Traductor"; [fr] diff --git a/modeldef.umisc b/modeldef.umisc index 32646c5..e707e6a 100644 --- a/modeldef.umisc +++ b/modeldef.umisc @@ -382,6 +382,35 @@ Model "FlareThrownX" FrameIndex FLAR A 0 1 } +Model "LightFlareThrown" +{ + Path "models" + Model 0 "LightFlareM_d.3d" + SurfaceSkin 0 0 "Jflare.png" + AngleOffset -90 + Offset 4 0 1 + Scale 0.1 -0.1 0.12 + USEACTORPITCH + USEROTATIONCENTER + Rotation-Center 0 0 1 + + FrameIndex FLAR A 0 0 +} +Model "DarkFlareThrown" +{ + Path "models" + Model 0 "LightFlareM_d.3d" + SurfaceSkin 0 0 "Jflare.png" + AngleOffset -90 + Offset 4 0 1 + Scale 0.1 -0.1 0.12 + USEACTORPITCH + USEROTATIONCENTER + Rotation-Center 0 0 1 + + FrameIndex FLAR A 0 0 +} + Model "UJumpBoots" { Path "models" @@ -435,9 +464,11 @@ Model "MinigunSentry" { Path "models" Model 0 "SentryGun_d.3d" - SurfaceSkin 0 1 "Minigun_.png" - SurfaceSkin 0 2 "minigun1_.png" + SurfaceSkin 0 1 "Minigun.png" + SurfaceSkin 0 2 "minigun1.png" Scale 0.15 0.15 0.18 + USEACTORPITCH + USEACTORROLL // down FrameIndex SENT A 0 0 @@ -517,16 +548,34 @@ Model "MinigunSentry" FrameIndex SENU Q 0 66 FrameIndex SENU R 0 67 } +Model "MinigunSentryX" +{ + Path "models" + Model 0 "SentryGun_d.3d" + SurfaceSkin 0 0 "JRifle1.png" + Scale 0.15 0.15 0.18 + USEACTORPITCH + USEACTORROLL + + FrameIndex SENF A 0 32 // shoot + FrameIndex SENF D 0 35 // shoot + FrameIndex SENF G 0 38 // shoot + FrameIndex SENF J 0 41 // shoot + FrameIndex SENF M 0 44 // shoot + FrameIndex SENF P 0 47 // shoot +} Model "MinigunSentryBase" { Path "models" Model 0 "SentryBase_d.3d" - SurfaceSkin 0 0 "Minigun_.png" - SurfaceSkin 0 1 "minigun1_.png" - SurfaceSkin 0 2 "JRifle1_.png" + SurfaceSkin 0 0 "Minigun.png" + SurfaceSkin 0 1 "minigun1.png" + SurfaceSkin 0 2 "JRifle1.png" Scale 0.15 0.15 0.18 ZOffset 38 + USEACTORPITCH + USEACTORROLL // down FrameIndex SENT A 0 0 diff --git a/models/LightFlareM_a.3d b/models/LightFlareM_a.3d index 5aa637872298c6806afd2d8fb274d5d813be85b2..cd2be24db4c397632b79be4a71f2bd6cf213b91a 100644 GIT binary patch literal 4204 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 GGXnr$f^~QR literal 4204 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 Gm;nGfBig+H diff --git a/sndinfo.txt b/sndinfo.txt index 17dd5ed..e08ca02 100644 --- a/sndinfo.txt +++ b/sndinfo.txt @@ -216,3 +216,12 @@ automag/click click automag/reload reload translator/event transa3 + +detector/start detact +detector/stop detend +detector/active detscan + +sentry/raise sentup +sentry/wind sentwind +sentry/fire sentfire +sentry/unwind sentuwnd diff --git a/zscript/biggun.zsc b/zscript/biggun.zsc index 7d6f49e..43aa3bd 100644 --- a/zscript/biggun.zsc +++ b/zscript/biggun.zsc @@ -81,7 +81,7 @@ Class BigGun : UnrealWeapon Tag "$T_BIGGUN"; Inventory.PickupMessage "$I_BIGGUN"; Weapon.UpSound "big/select"; - Weapon.SlotNumber 0; + Weapon.SlotNumber 9; Weapon.SelectionOrder 0; Weapon.AmmoType "BigAmmo"; Weapon.AmmoUse 1; diff --git a/zscript/miscitems.zsc b/zscript/miscitems.zsc index 2625577..a0db32f 100644 --- a/zscript/miscitems.zsc +++ b/zscript/miscitems.zsc @@ -713,6 +713,36 @@ Class BetaFlare : UnrealInventory if ( Owner ) Owner.RemoveInventory(self); Destroy(); } + override bool Use( bool pickup ) + { + if ( pickup || bActive || (charge < defaultcharge) ) return false; + Vector3 x, y, z; + [x, y, z] = dt_CoordUtil.GetAxes(Owner.pitch,Owner.angle,Owner.roll); + Vector3 origin = level.Vec3Offset(Owner.Vec2OffsetZ(0,0,Owner.player.viewz),x*10.-z*8.); + let a = Spawn(ThrownClass,origin); + a.target = Owner; + a.angle = Owner.angle; + a.pitch = Owner.pitch; + a.vel += x*a.speed; + for ( Inventory i=Owner.Inv; i; i=i.Inv ) + { + if ( !(i is 'BetaFlare') ) continue; + UnrealInventory(i).bActive = true; + UnrealInventory(i).Charge = 0; + i.tracer = a; + } + return false; + } + override void DoEffect() + { + Super.DoEffect(); + if ( !bActive ) + { + charge = min(defaultcharge,charge+1); + return; + } + else if ( !tracer ) bActive = false; + } Default { Inventory.MaxAmount 1; @@ -728,6 +758,7 @@ Class LightFlare : BetaFlare { Tag "$T_LFLARES"; Inventory.Icon "I_FlarBL"; + BetaFlare.ThrownClass "LightFlareThrown"; } } @@ -737,19 +768,232 @@ Class DarkFlare : BetaFlare { Tag "$T_DFLARES"; Inventory.Icon "I_FlarBD"; + BetaFlare.ThrownClass "DarkFlareThrown"; } } -Class BetaFlareThrown +Class BetaFlareThrown : Actor { + double pitchvel, anglevel, rollvel; + double desiredangle; + bool rotatetodesired; + double lastpitch, lastangle, lastroll; + Actor b; + Default + { + Radius 6; + Height 6; + +NOBLOCKMAP; + +MISSILE; + +MOVEWITHSECTOR; + +THRUACTORS; + +USEBOUNCESTATE; + +INTERPOLATEANGLES; + +BOUNCEAUTOOFF; + +BOUNCEAUTOOFFFLOORONLY; + +NOTELEPORT; + +FORCERADIUSDMG; + +NODAMAGETHRUST; + DamageType "Exploded"; + Speed 12; + VSpeed 2; + Mass 1; + Gravity 0.35; + BounceType "Hexen"; + WallBounceFactor 0.6; + BounceFactor 0.6; + ReactionTime 350; + } + virtual void A_SpawnEffect() + { + } + override void PostBeginPlay() + { + Super.PostBeginPlay(); + pitchvel = FRandom[Junk](5,15)*RandomPick[Junk](-1,1); + anglevel = FRandom[Junk](5,15)*RandomPick[Junk](-1,1); + rollvel = FRandom[Junk](5,15)*RandomPick[Junk](-1,1); + } + override void Tick() + { + lastpitch = pitch; + lastangle = angle; + lastroll = roll; + Super.Tick(); + if ( rotatetodesired ) + { + if ( deltaangle(pitch,0) ~== 0 ) pitch = 0; + else pitch += clamp(deltaangle(pitch,0),-pitchvel,pitchvel); + if ( deltaangle(angle,desiredangle) ~== 0 ) angle = desiredangle; + else angle += clamp(deltaangle(angle,desiredangle),-anglevel,anglevel); + if ( deltaangle(roll,0) ~== 0 ) roll = 0; + else roll += clamp(deltaangle(roll,0),-rollvel,rollvel); + } + else + { + angle += anglevel; + pitch += pitchvel; + roll += rollvel; + } + if ( ReactionTime <= 0 ) return; + if ( GetAge() < 9 ) return; + if ( waterlevel > 0 ) + { + if ( tracer ) tracer.Destroy(); + if ( b ) b.Destroy(); + A_StopSound(CHAN_VOICE); + ReactionTime = 0; + return; + } + if ( !b ) + { + A_PlaySound("flare/on"); + A_PlaySound("flare/loop",CHAN_VOICE,.5,true); + b = Spawn("FlareHitbox",pos); + b.master = self; + } + b.A_AlertMonsters(0,AMF_TARGETEMITTER); + ReactionTime--; + } + States + { + Spawn: + FLAR A 1 + { + if ( GetAge() >= 9 ) A_SpawnEffect(); + return A_JumpIf(ReactionTime<=0,"Death"); + } + Wait; + Bounce: + FLAR A 0 + { + pitch = lastpitch; + angle = lastangle; + roll = lastroll; + rotatetodesired = true; + desiredangle = FRandom[Junk](0,360); + pitchvel = abs(pitchvel)*0.75; + anglevel = abs(anglevel)*0.75; + rollvel = abs(rollvel)*0.75; + } + Goto Spawn; + Death: + FLAR A 0 { anglevel *= 0; } + FLAR A 1 + { + if ( waterlevel > 0 ) + { + if ( b ) b.Destroy(); + A_StopSound(CHAN_VOICE); + return ResolveState("Fizz"); + } + A_SpawnEffect(); + return A_JumpIf(ReactionTime<=0,1); + } + Wait; + FLAR A 0 + { + if ( b ) b.Destroy(); + if ( waterlevel > 0 ) return ResolveState("Fizz"); + A_RemoveLight('PLight'); + A_StopSound(CHAN_VOICE); + A_PlaySound("flare/explode"); + A_Explode(50,50); + A_NoGravity(); + A_Stop(); + A_SetRenderStyle(1.,STYLE_Add); + SetZ(pos.z+9); + Spawn("FlareXLight",pos); + bMOVEWITHSECTOR = false; + bFORCEXYBILLBOARD = true; + A_SetScale(FRandomPick[ExploS](-1.5,1.5),FRandomPick[ExploS](-1.5,1.5)); + return A_Jump(256,"Explo1","Explo2","Explo3","Explo4","Explo5"); + } + Explo1: + EXP1 ABCDEFGH 3 Bright; + Stop; + Explo2: + EXP2 ABCDEFGH 3 Bright; + Stop; + Explo3: + EXP3 ABCDEFGH 3 Bright; + Stop; + Explo4: + EXP4 ABCDEFGH 3 Bright; + Stop; + Explo5: + EXP5 ABCDEFGH 3 Bright; + Stop; + Fizz: + FLAR A 0 A_RemoveLight('PLight'); + FLAR A 1 + { + special1++; + if ( special1 > 150 ) A_FadeOut(); + } + Wait; + } } Class LightFlareThrown : BetaFlareThrown { + override void A_SpawnEffect() + { + Vector3 x, y, z; + double a, s; + [x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll); + for ( int i=0; i<4; i++ ) + { + a = FRandom[BFlare](0,360); + s = FRandom[BFlare](0,0.15); + let t = Spawn("LightFlareParticle",pos+x*4+z); + t.vel = (x+y*cos(a)*s+z*sin(a)*s).unit()*FRandom[BFlare](1,4); + } + } + override void Tick() + { + Super.Tick(); + if ( GetAge() == 9 ) A_AttachLightDef('PLight','LIGHTFLARE'); + } } Class DarkFlareThrown : BetaFlareThrown { + override void A_SpawnEffect() + { + Vector3 x, y, z; + double a, s; + [x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll); + for ( int i=0; i<3; i++ ) + { + a = FRandom[BFlare](0,360); + s = FRandom[BFlare](0,0.5); + let t = Spawn("DarkFlareParticle",pos+x*4+z); + t.vel = (x+y*cos(a)*s+z*sin(a)*s).unit()*FRandom[BFlare](4,8); + } + } + override void Tick() + { + Super.Tick(); + if ( GetAge() == 9 ) A_AttachLightDef('PLight','DARKFLARE'); + } +} + +Class LightFlareParticle : UTSmoke +{ + Default + { + StencilColor "FFFFFF"; + Scale 0.2; + } +} +Class DarkFlareParticle : UTSmoke +{ + Default + { + StencilColor "000000"; + Scale 2.2; + } } Class Dampener : UnrealInventory @@ -1123,6 +1367,46 @@ Class SentryItem : UnrealInventory Inventory.RespawnTics 1050; UnrealInventory.Charge 300; } + override bool Use( bool pickup ) + { + if ( pickup ) return false; + if ( bActive ) return false; + Vector3 x, y, z; + [x, y, z] = dt_CoordUtil.GetAxes(Owner.pitch,Owner.angle,Owner.roll); + Vector3 origin = level.Vec3Offset(Owner.Vec2OffsetZ(0,0,Owner.player.viewz),x*90.); + origin = level.Vec3Offset(origin,(0,0,-GetDefaultByType("MinigunSentryBase").Height*.5)); + if ( !level.IsPointInLevel(origin) ) + { + if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_MSNOROOM")); + return false; + } + let a = Spawn("MinigunSentryBase",origin); + if ( !a.TestMobjLocation() ) + { + if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_MSNOROOM")); + a.Destroy(); + return false; + } + bActive = true; + tracer = a; + a.target = Owner; + a.angle = Owner.angle; + a.pitch = 0; + a.roll = 0; + return false; + } + override void DoEffect() + { + Super.DoEffect(); + if ( !bActive ) return; + if ( !tracer ) + { + bActive = false; + DepleteOrDestroy(); + return; + } + Charge = tracer.Health; + } States { Spawn: @@ -1131,9 +1415,125 @@ Class SentryItem : UnrealInventory } } +// overlay for muzzle flash +Class MinigunSentryX : Actor +{ + Default + { + RenderStyle "Add"; + +NOGRAVITY; + +NOBLOCKMAP; + +INTERPOLATEANGLES; + } + override void Tick() + { + Super.Tick(); + if ( !tracer || !tracer.InStateSequence(tracer.CurState,tracer.FindState("MissileLoop")) ) + { + Destroy(); + return; + } + SetOrigin(tracer.pos,true); + angle = tracer.angle; + pitch = tracer.pitch; + roll = tracer.roll; + } + States + { + Spawn: + SENF A 1 Bright; + TNT1 A 2; + SENF D 1 Bright; + TNT1 A 2; + SENF G 1 Bright; + TNT1 A 2; + SENF J 1 Bright; + TNT1 A 2; + SENF M 1 Bright; + TNT1 A 2; + SENF P 1 Bright; + TNT1 A 2; + Stop; + } +} + // The "head" of the sentry, attaches to the body Class MinigunSentry : Actor { + const maxangle = 60; + const maxpitch = 30; + + Default + { + +NOGRAVITY; + +NOBLOCKMAP; + +INTERPOLATEANGLES; + +FRIENDLY; + } + override void Tick() + { + Super.Tick(); + if ( !master ) + { + Destroy(); + return; + } + Vector3 x, y, z; + [x, y, z] = dt_CoordUtil.GetAxes(master.pitch,master.angle,master.roll); + SetOrigin(level.Vec3Offset(master.pos,z*38),true); + } + double _PitchTo( Actor other ) + { + if ( !other ) return 0; + Vector3 otherpos = level.Vec3Diff(pos,other.Vec3Offset(0,0,other.height/2)); + double dist = otherpos.length(); + if ( dist > 0 ) return -asin(otherpos.z/dist); + return 0; + } + bool TargetVisible() + { + if ( !target || (target.Health <= 0) || !CheckSight(target) ) return false; + double angledelta = DeltaAngle(master.angle,AngleTo(target)); + double pitchdelta = DeltaAngle(master.pitch,_PitchTo(target)); + if ( (abs(angledelta) > maxangle) || (abs(pitchdelta) > maxpitch) ) return false; + return true; + } + void A_SentryFaceTarget() + { + if ( !TargetVisible() ) return; + double angledelta = DeltaAngle(angle,AngleTo(target)); + double pitchdelta = DeltaAngle(pitch,_PitchTo(target)); + double angleturn = clamp(abs(angledelta)*0.1,2,15); + double pitchturn = clamp(abs(pitchdelta)*0.1,2,15); + angle = clamp(angle+clamp(angledelta,-angleturn,angleturn),master.angle-maxangle,master.angle+maxangle); + pitch = clamp(pitch+clamp(pitchdelta,-pitchturn,pitchturn),master.pitch-maxpitch,master.pitch+maxpitch); + } + void A_SentryFaceDir( int dest, statelabel next ) + { + double angledelta = DeltaAngle(angle,master.angle+dest); + double pitchdelta = DeltaAngle(pitch,master.pitch); + if ( max(abs(angledelta),abs(pitchdelta)) < 2 ) + { + angle = master.angle+dest; + pitch = master.pitch; + SetStateLabel(next); + return; + } + angle = clamp(angle+clamp(angledelta,-2,2),master.angle-maxangle,master.angle+maxangle); + pitch = clamp(pitch+clamp(pitchdelta,-2,2),master.pitch-maxpitch,master.pitch+maxpitch); + } + void A_SentryAttack() + { + special1 = max(0,special1-1); + if ( (special1 <= 0) && master.master && master.master.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_SENTRYDRY")); + A_SentryFaceTarget(); + A_PlaySound("sentry/fire",CHAN_WEAPON); + Vector3 x, y, z; + [x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll); + // TODO actually fire bullets + let c = Spawn("UCasing",level.Vec3Offset(pos,-x*7+y*2+z*2)); + c.vel = x*FRandom[Junk](-1.5,1.5)+y*FRandom[Junk](2,4)+z*FRandom[Junk](2,3); + } States { Spawn: @@ -1142,23 +1542,164 @@ Class MinigunSentry : Actor SENR ABCDEFGHIJKLMNO 3; Goto Idle; Idle: - SENI A 1; + SENI A 1 A_SentryFaceDir(0,1); Wait; - Fire: - SENW ABCDEFGHIJKLMNOPQR 1; - Goto FireLoop; - FireLoop: - SENF ABCDEFGHIJKLMNOPQR 1; + SENI A 1 + { + A_LookEx(LOF_NOSOUNDCHECK|LOF_NOJUMP); + A_SentryFaceDir(-maxangle,1); + return A_JumpIf(TargetVisible(),"See"); + } + Wait; + SENI AAAAAA 1 + { + A_LookEx(LOF_NOSOUNDCHECK|LOF_NOJUMP); + return A_JumpIf(TargetVisible(),"See"); + } + SENI A 1 + { + A_LookEx(LOF_NOSOUNDCHECK|LOF_NOJUMP); + A_SentryFaceDir(maxangle,1); + return A_JumpIf(TargetVisible(),"See"); + } + Wait; + SENI AAAAAA 1 + { + A_LookEx(LOF_NOSOUNDCHECK|LOF_NOJUMP); + return A_JumpIf(TargetVisible(),"See"); + } + Goto Idle+1; + See: + SENI A 1 + { + if ( !TargetVisible() ) + { + A_ClearTarget(); + return ResolveState("Idle"); + } + A_SentryFaceTarget(); + if ( special1 > 0 ) A_Chase(null,"Missile",flags:CHF_DONTMOVE|CHF_DONTTURN); + return ResolveState(null); + } + Wait; + Missile: + SENW A 0 + { + A_PlaySound("sentry/wind",looping:true); + master.SetStateLabel("Missile"); + } + SENW ABCDEFGHIJKLMNOPQR 1 A_SentryFaceTarget(); + Goto MissileLoop; + MissileLoop: + SENF A 0 + { + let f = Spawn("MinigunSentryX",pos); + f.angle = angle; + f.pitch = pitch; + f.roll = roll; + f.tracer = self; + } + SENF A 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd"); + SENF A 1 A_SentryAttack(); + SENF BC 1 A_SentryFaceTarget(); + SENF D 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd"); + SENF D 1 A_SentryAttack(); + SENF EF 1 A_SentryFaceTarget(); + SENF G 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd"); + SENF G 1 A_SentryAttack(); + SENF HI 1 A_SentryFaceTarget(); + SENF J 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd"); + SENF J 1 A_SentryAttack(); + SENF KL 1 A_SentryFaceTarget(); + SENF M 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd"); + SENF M 1 A_SentryAttack(); + SENF NO 1 A_SentryFaceTarget(); + SENF P 0 A_JumpIf(!TargetVisible()||(special1<=0),"MissileEnd"); + SENF P 1 A_SentryAttack(); + SENF QR 1 A_SentryFaceTarget(); Loop; - FireEnd: - SENU ABCDEFGHIJKLMNOPQR 1; - Goto Idle; + MissileEnd: + SENU A 0 + { + A_PlaySound("sentry/unwind"); + master.SetStateLabel("MissileEnd"); + } + SENU ABCDEFGHIJKLMNOPQR 1 A_SentryFaceTarget(); + Goto See; } } // The body of the sentry Class MinigunSentryBase : Actor { + const sentryammo = 200; + + Default + { + Health 300; + Mass int.max; + Radius 12; + Height 48; + +SOLID; + +SHOOTABLE; + +NOBLOOD; + +DONTTHRUST; + } + override void PostBeginPlay() + { + Super.PostBeginPlay(); + if ( master && master.player ) SetTag(String.Format(StringTable.Localize("$T_OWNEDSENTRY"),master.player.GetUserName()); + else SetTag(StringTable.Localize("$T_SENTRY")); + tracer = Spawn("MinigunSentry",pos); + tracer.special1 = sentryammo; + tracer.master = self; + tracer.angle = angle; + tracer.pitch = pitch; + tracer.roll = roll; + Vector3 x, y, z; + [x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll); + tracer.SetOrigin(level.Vec3Offset(pos,z*38),false); + if ( !deathmatch ) return; + if ( master && master.player ) tracer.SetFriendPlayer(master.player); + else tracer.bFRIENDLY = false; + } + override string GetObituary( Actor victim, Actor inflictor, Name mod, bool playerattack ) + { + if ( victim == master ) return String.Format(StringTable.Localize("$O_OWNSENTRY"),GetTag()); + return String.Format(StringTable.Localize("$O_SENTRY"),GetTag()); + } + override void Touch( Actor toucher ) + { + if ( !toucher.player ) return; + if ( deathmatch ) + { + if ( master && (toucher != master) && master.CheckLocalView() ) + Console.Printf(StringTable.Localize("$M_SENTRYHIJACK")); + master = toucher; + SetTag(String.Format(StringTable.Localize("$T_OWNEDSENTRY"),toucher.player.GetUserName()); + tracer.A_ClearTarget(); + tracer.SetFriendPlayer(toucher.player); + } + let amo = toucher.FindInventory("UMiniAmmo"); + if ( !amo || (amo.Amount <= 0) || (tracer.special1 >= sentryammo) ) return; + A_PlaySound("misc/i_pkup",CHAN_ITEM); + int xammo = min(sentryammo-tracer.special1,amo.Amount); + tracer.special1 += xammo; + amo.Amount -= xammo; + } + override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle ) + { + int dmg = Super.DamageMobj(inflictor,source,damage,mod,flags,angle); + if ( !tracer.target ) tracer.target = target; + return dmg; + } + override void Die( Actor source, Actor inflictor, int dmgflags, Name MeansOfDeath ) + { + if ( master && master.CheckLocalView() ) + Console.Printf(StringTable.Localize("$M_SENTRYDOWN")); + if ( tracer ) tracer.Destroy(); + Super.Die(source,inflictor,dmgflags,MeansOfDeath); + } States { Spawn: @@ -1168,13 +1709,13 @@ Class MinigunSentryBase : Actor Idle: SENI A 1; Wait; - Fire: + Missile: SENW ABCDEFGHIJKLMNOPQR 1; - Goto FireLoop; - FireLoop: + Goto MissileLoop; + MissileLoop: SENF ABCDEFGHIJKLMNOPQR 1; Loop; - FireEnd: + MissileEnd: SENU ABCDEFGHIJKLMNOPQR 1; Goto Idle; } diff --git a/zscript/ueightball.zsc b/zscript/ueightball.zsc index 9bc8cd7..3b9a02c 100644 --- a/zscript/ueightball.zsc +++ b/zscript/ueightball.zsc @@ -517,9 +517,9 @@ Class Eightball : UnrealWeapon Ready2: EBLS O 0 A_CheckReload(); EBLL A 0 A_PlaySound("utrl/load",CHAN_ITEM,Dampener.Active(self)?.1:1.); - EBLL ABCDEFGHIJK 2 A_WeaponReady(WRF_NOFIRE); + EBLL ABCDEFGHIJK 2; EBLL L 0 A_PlaySound("utrl/rotate",CHAN_ITEM,Dampener.Active(self)?.01:.1); - EBLL LMNOPQRSTUVWXYZ[ 1 A_WeaponReady(WRF_NOFIRE); + EBLL LMNOPQRSTUVWXYZ[ 1; EBLL Z 0; // force no tweening EBLI A 0; Goto Idle; diff --git a/zscript/unrealcommon.zsc b/zscript/unrealcommon.zsc index b625a15..2a87226 100644 --- a/zscript/unrealcommon.zsc +++ b/zscript/unrealcommon.zsc @@ -1113,6 +1113,11 @@ Class UnrealMainHandler : EventHandler } } } + else if ( (e.Name ~== "usetranslator") && (e.player != -1) && playeringame[e.player] && !menuactive ) + { + let t = players[e.player].mo.FindInventory("UTranslator"); + if ( t ) t.Use(false); + } } override void WorldLoaded( WorldEvent e ) { diff --git a/zscript/unrealhud.zsc b/zscript/unrealhud.zsc index 80c1b2a..fd0ec22 100644 --- a/zscript/unrealhud.zsc +++ b/zscript/unrealhud.zsc @@ -375,7 +375,7 @@ Class UnrealHUD : BaseStatusBar if ( Prev && !Next && !bDrawOne ) x += 32; // this was missing from the original, causing a gap when there's only two items in the inventory if ( Prev ) { - bRed = ((Prev is 'UnrealInventory') && UnrealInventory(Prev).bActive) || (Prev is 'Powerup') || ((Prev is 'UTranslator') && bFlashTranslator); + bRed = ((Prev is 'UnrealInventory') && UnrealInventory(Prev).bActive) || (Prev is 'Powerup') || ((Prev is 'UTranslator') && ((bTranslatorActive) || (bFlashTranslator && ((gametic%8)<4)))); DrawHudIcon(x,y,Prev,bRed); if ( Prev.MaxAmount > 1 ) DrawNumberOf(Prev,x,y); } @@ -389,7 +389,7 @@ Class UnrealHUD : BaseStatusBar if ( SelectedItem.MaxAmount > 1 ) DrawNumberOf(SelectedItem,CurX,y); if ( Next ) { - bRed = ((Next is 'UnrealInventory') && UnrealInventory(Next).bActive) || (Next is 'Powerup') || ((Next is 'UTranslator') && bFlashTranslator); + bRed = ((Next is 'UnrealInventory') && UnrealInventory(Next).bActive) || (Next is 'Powerup') || ((Next is 'UTranslator') && ((bTranslatorActive) || (bFlashTranslator && ((gametic%8)<4)))); DrawHudIcon(x+64,y,Next,bRed); if ( Next.MaxAmount > 1 ) DrawNumberOf(Next,x+64,y); } diff --git a/zscript/upowerups.zsc b/zscript/upowerups.zsc index 947125c..87b2cf2 100644 --- a/zscript/upowerups.zsc +++ b/zscript/upowerups.zsc @@ -322,6 +322,9 @@ Class UJumpBoots : UnrealInventory Class MotionDetector : UnrealInventory { + ui TextureID DetHud, DetSpot[2]; + Array nearscan; + Default { Tag "$T_DETECTOR"; @@ -332,8 +335,76 @@ Class MotionDetector : UnrealInventory Inventory.Icon "I_Detect"; Inventory.PickupMessage "$I_DETECTOR"; Inventory.RespawnTics 1050; - UnrealInventory.Charge 3500; + UnrealInventory.Charge 7000; } + override bool TryPickup( in out Actor toucher ) + { + bool valid = Super.TryPickup(toucher); + if ( valid ) level.allmap = true; + return valid; + } + override void PostRender( double lbottom ) + { + if ( !bActive ) return; + double xpos = UnrealHUD(StatusBar).ClipX-96; + double ypos = 0; + // offset if inventory display present on top right + if ( UnrealHUD(StatusBar).HudMode < 2 ) ypos += 32; + if ( DetHud.IsNull() ) DetHud = TexMan.CheckForTexture("DetHud",TexMan.Type_Any); + if ( DetSpot[0].IsNull() ) DetSpot[0] = TexMan.CheckForTexture("DetSpot0",TexMan.Type_Any); + if ( DetSpot[1].IsNull() ) DetSpot[1] = TexMan.CheckForTexture("DetSpot1",TexMan.Type_Any); + Screen.DrawTexture(DetHud,false,xpos,ypos,DTA_VirtualWidthF,UnrealHUD(StatusBar).ClipX,DTA_VirtualHeightF,UnrealHUD(StatusBar).ClipY,DTA_KeepRatio,true); + double alph = max(0.,0.25+0.75*sin((gametic+UnrealHUD(StatusBar).fractic)*6.)); + Screen.Dim(Color("FF 40 00"),alph*.25,int((xpos+3)*UnrealHUD(StatusBar).scalev.x),int((ypos+3)*UnrealHUD(StatusBar).scalev.y),int(90*UnrealHUD(StatusBar).scalev.x),int(90*UnrealHUD(StatusBar).scalev.y)); + Screen.DrawTexture(DetSpot[0],false,xpos+48,ypos+48,DTA_VirtualWidthF,UnrealHUD(StatusBar).ClipX,DTA_VirtualHeightF,UnrealHUD(StatusBar).ClipY,DTA_KeepRatio,true); + alph = max(0.,0.5+0.5*sin((gametic+UnrealHUD(StatusBar).fractic-10)*6.)); + for ( int i=0; i 48. ) continue; + // this is a long line, but it's not the longest I've ever seen + // oh I have seen things... php code that would make you want to stab your eyes with forks... + Screen.DrawTexture(DetSpot[1],false,xpos+48+relofs.x,ypos+48+relofs.y,DTA_VirtualWidthF,UnrealHUD(StatusBar).ClipX,DTA_VirtualHeightF,UnrealHUD(StatusBar).ClipY,DTA_KeepRatio,true,DTA_Alpha,alph,DTA_ClipLeft,int((xpos+3)*UnrealHUD(StatusBar).scalev.x),DTA_ClipTop,int((ypos+3)*UnrealHUD(StatusBar).scalev.y),DTA_ClipRight,int((xpos+93)*UnrealHUD(StatusBar).scalev.x),DTA_ClipBottom,int((ypos+93)*UnrealHUD(StatusBar).scalev.y)); + } + } + override bool Use( bool pickup ) + { + if ( pickup ) return false; + bActive = !bActive; + if ( bActive ) Owner.A_PlaySound("detector/start",CHAN_ITEM); + else Owner.A_PlaySound("detector/stop",CHAN_ITEM,0.1,false,3.); + return false; + } + override void DoEffect() + { + Super.DoEffect(); + if ( bActive && !tracer ) + { + tracer = Spawn("DetectorSound",Owner.pos); + tracer.target = Owner; + tracer.master = self; + } + else if ( !bActive && tracer ) tracer.Destroy(); + if ( !bActive ) return; + nearscan.Clear(); + let bi = BlockThingsIterator.Create(Owner,2048); + while ( bi.Next() ) + { + if ( !bi.Thing || (bi.Thing == Owner) || !bi.Thing.bISMONSTER || bi.Thing.Health <= 0 ) continue; + nearscan.Push(bi.Thing); + } + if ( (Charge <= 0) || DrainCharge(1) ) + { + Owner.A_PlaySound("detector/stop",CHAN_ITEM,0.1,false,3.); + if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_DETECTOR")); + if ( tracer ) tracer.Destroy(); + DepleteOrDestroy(); + } + } + States { Spawn: @@ -342,6 +413,39 @@ Class MotionDetector : UnrealInventory } } +Class DetectorSound : Actor +{ + Default + { + +NOBLOCKMAP; + +NOGRAVITY; + } + override void Tick() + { + Super.Tick(); + if ( !target || !master ) + { + Destroy(); + return; + } + SetOrigin(target.pos,true); + A_SoundVolume(CHAN_VOICE,target.CheckLocalView()?0.1:0.0); + A_SoundVolume(CHAN_7,!target.CheckLocalView()?0.1:0.0); + } + override void PostBeginPlay() + { + Super.PostBeginPlay(); + A_PlaySound("detector/active",CHAN_VOICE,0.1,true,ATTN_NONE); + A_PlaySound("detector/active",CHAN_7,0.1,true,3.); + } + override void OnDestroy() + { + Super.OnDestroy(); + A_StopSound(CHAN_VOICE); + A_StopSound(CHAN_7); + } +} + Class SCUBAGear : UnrealInventory { Default diff --git a/zscript/utranslocator.zsc b/zscript/utranslocator.zsc index e88b836..22844af 100644 --- a/zscript/utranslocator.zsc +++ b/zscript/utranslocator.zsc @@ -40,7 +40,7 @@ Class UTranslocator : UnrealWeapon { Tag "$T_TELEGUN"; Inventory.PickupMessage "$I_TELEGUN"; - Weapon.SlotNumber 9; + Weapon.SlotNumber 1; Weapon.SelectionOrder 10; Weapon.AmmoType1 "UTranslocatorAmmo"; Weapon.AmmoUse1 1;