diff --git a/README.md b/README.md index 6e8092626..f39581d3f 100644 --- a/README.md +++ b/README.md @@ -276,10 +276,12 @@ Popularly known as the ***"Death Cannon"***. One of the four ultimate weapons co Unlike its previous incarnation in **SWWM Platinum**, this one doesn't have such an obscene pre-fire delay, so it's much easier to land a shot (not to mention also being far more lethal, thanks to the added chain reaction effect). +Due to its rarity, you can't buy it from the store, so you gotta find one in the field. + ### Crystal Box ![](docimg/ynykronammo.png) -Additional ammo charge for the **Ynykron Artifact**. Contains a rod of polarized **Puronokorokinylum** crystal, highly volatile when heated and stimulated with concentrated light. These don't spawn in the world, so you'll have to get more ammo by finding additional weapon pickups or managing to afford one in the store, or trying your luck with a **Chancebox**. +Additional ammo charge for the **Ynykron Artifact**. Contains a rod of polarized **Puronokorokinylum** crystal, highly volatile when heated and stimulated with concentrated light. These don't spawn in the world, and cannot be bought, so you'll have to get more ammo by finding additional weapon pickups or trying your luck with a **Chancebox**. ## The Pickups ![](docimg/demolitionist_items.png) @@ -401,31 +403,31 @@ A floating lamp companion, may attract moths. The moths will disperse and attack Reveals the entire layout of the map and shows key locations in the HUD. Also allows you to highlight pickups through walls when holding the **Item Sense** button. +### Safety Tether ~ Replaces Chaos Device +![](docimg/tether.png) + +On use, teleports you back to the start of the map. Basically acts exactly the same as a Chaos Device, although it also resets you to max health should you be under the weather. Additionally it also generates shockwaves on both ends, making your escape more dramatic. + ### Mykradvo Artifact ~ May randomly replace Ghost Artifact or Invinciball ![](docimg/mykradvo.png) When used, bursts into plasma tendrils that will seek all hostiles within 100m and fry them good. If there are no hostiles around, the artifact will simply not ignite. -Has a chance to spawn in place of other items, but only one may spawn per map. +Has a chance to spawn in place of other items, but only one may spawn per map. Cannot be bought due to its rarity. ### Divine Sprite ~ May randomly replace Grilled Cheese Sandwich ![](docimg/sprite.png) Rapidly boosts your health dramatically, for 30 seconds. Its effects will obviously fade afterwards. Your HUD can't exactly report your actual health, but it's assumed this goes way beyond the one thousand cap, somehow. -Only one may spawn per map, use it wisely. +Only one may spawn per map, and you can't buy these either. If you manage to fetch one, use it wisely. ### Devastation Sigil ~ May randomly replace Ragekit ![](docimg/deva.png) 20 seconds of absolute destructive potential for any damage you may deal, including to yourself (so be careful). -Same spawn conditions as the other two. - -### Safety Tether ~ Replaces Chaos Device -![](docimg/tether.png) - -On use, teleports you back to the start of the map. Basically acts exactly the same as a Chaos Device, although it also resets you to max health should you be under the weather. Additionally it also generates shockwaves on both ends, making your escape more dramatic. +Same conditions as the other two. Make sure you find the perfect chance to unleash this beast. ## The Collectibles ![](docimg/chancebox.png) diff --git a/gldefs.pickups b/gldefs.pickups index cdd9cb681..0b7dfd17a 100644 --- a/gldefs.pickups +++ b/gldefs.pickups @@ -112,6 +112,7 @@ HardwareShader Texture "models/DivineSprite.png" Brightmap Texture "models/DivineSprite.png" { map "models/DivineSprite_mask.png" + DisableFullbright } HardwareShader Texture "models/DevaSigil.png" { @@ -119,6 +120,23 @@ HardwareShader Texture "models/DevaSigil.png" Texture "masktex" "models/DevaSigil_mask.png" Texture "envtex" "models/matcap/dekamap.png" } +Brightmap Texture "models/SafetyTether.png" +{ + map "models/SafetyTether_bright.png" + DisableFullbright +} +HardwareShader Texture "models/SafetyTether.png" +{ + Shader "shaders/glsl/Shinemask.fp" + Texture "masktex" "models/SafetyTether_mask.png" + Texture "envtex" "models/matcap/silvermap.png" +} +HardwareShader Texture "models/SafetyTether_off.png" +{ + Shader "shaders/glsl/Shinemask.fp" + Texture "masktex" "models/SafetyTether_mask.png" + Texture "envtex" "models/matcap/silvermap.png" +} PointLight ARMORNUGGETLIGHT { @@ -316,3 +334,15 @@ Object AngerySigilX { Frame "BLPS" { light "DEVASLIGHT" } } + +PointLight SAFETYLIGHT +{ + Color 0.2 1.0 0.3 + Size 50 + Attenuate 1 +} + +Object SafetyTether +{ + Frame "XZW1B" { light "SAFETYLIGHT" } +} diff --git a/graphics/HUD/Icons/I_Safety.png b/graphics/HUD/Icons/I_Safety.png index 7b43c4c2f..4c3ab3dbc 100644 Binary files a/graphics/HUD/Icons/I_Safety.png and b/graphics/HUD/Icons/I_Safety.png differ diff --git a/graphics/HUD/Icons/I_SafetyNo.png b/graphics/HUD/Icons/I_SafetyNo.png new file mode 100644 index 000000000..de478f1c0 Binary files /dev/null and b/graphics/HUD/Icons/I_SafetyNo.png differ diff --git a/graphics/HUD/Icons/I_SafetyOn.png b/graphics/HUD/Icons/I_SafetyOn.png new file mode 100644 index 000000000..30b1ed93c Binary files /dev/null and b/graphics/HUD/Icons/I_SafetyOn.png differ diff --git a/graphics/HUD/Icons/I_SafetyYes.png b/graphics/HUD/Icons/I_SafetyYes.png new file mode 100644 index 000000000..c4b933d1d Binary files /dev/null and b/graphics/HUD/Icons/I_SafetyYes.png differ diff --git a/language.def_base b/language.def_base index c986037e4..d8ac0a477 100644 --- a/language.def_base +++ b/language.def_base @@ -644,6 +644,7 @@ D_FROGGY1 = "\cjA small price to pay...\c-"; D_FROGGY2 = "\cj... for \cdFroggy Chair\cj.\c-"; D_BARRIER = "The Elemental Coating wore off."; D_DEVASTATION = "The Sigil's power is no more."; +D_TETHERFAIL = "The Safety Tether link was obstructed."; D_MASHIRO = "\cjShe knows where you are...\c-"; SWWM_YNYKRONREADY = "Ynykron Artifact ready for firing."; SWWM_SWAPWEAPON = "\cjPress \cfUse\cj to swap \cf%s\cj for \cf%s\cj.\c-"; diff --git a/language.def_lore b/language.def_lore index 75e9dde26..cffec7eeb 100644 --- a/language.def_lore +++ b/language.def_lore @@ -3251,7 +3251,7 @@ SWWM_LORETXT_RYUJI = "\cfI'm not crying, I swear.\c-"; SWWM_LORETAG_SAFETYTETHER = "Safety Tether"; SWWM_LORETAB_SAFETYTETHER = "Item"; -SWWM_LOREREL_SAFETYTETHER = "AkariLabs;Cyrus;LuckyCollar;Parthoris;Sidhe;Cronos;Saya;UAC"; +SWWM_LOREREL_SAFETYTETHER = "AkariLabs;Cyrus;LuckyCollar;Parthoris;Sidhe;Cronos;Saya;UAC;Unissix"; SWWM_LORETXT_SAFETYTETHER = "\cxDesignation:\c-\n" "\cf Safety Tether\c-\n" @@ -3263,10 +3263,14 @@ SWWM_LORETXT_SAFETYTETHER = "\n" "What you see here is an extension of the magic employed in your \cfLucky Collar\c-, repurposed and adjusted to allow you to transport yourself on demand back to the entrance of the current area you're in. This is quite useful to have in case you find yourself trapped in some inescapable room, and have no other resources to break out. The world of \cfParthoris\c- is a treacherous one, as the \cfSidhe\c- would inform us, and so these are a must, and may be found in areas where \"trap rooms\" have been reported.\n" "\n" +"Simply twist both ends in opposing directions, and the device will prime. If the user is already standing close enough to the destination, the warp will be cancelled in order to prevent an accidental misuse, otherwise, the lights will turn blue and the warp will be performed.\n" +"\n" "\cxSaya's Notes:\c-\n" "\cfAh, the perfect way to escape from a closed room...\c-\n" "\n" -"\cfYeah, this is actually based on your collar, works similarly too, except I'm not the one who activates whenever you're in mortal danger, and its effects are more \"dramatic\" (you'll see). It's simple magic stuff, really. Those idiots at the UAC would shit themselves if they knew we've had the magic to do long distance teleports, even across universes, long before their experiments existed.\c-"; +"\cfYeah, this is actually based on your collar, works similarly too, except I'm not the one who activates whenever you're in mortal danger, and its effects are more \"dramatic\" (you'll see). It's simple magic stuff, really. Those idiots at the UAC would shit themselves if they knew we've had the magic to do long distance teleports, even across universes, long before their experiments existed.\c-\n" +"\n" +"\cfI hope Misa doesn't mind that I pretty much repurposed one of her grenade designs for this.\c-"; SWWM_LORETXT_SAFETYTETHER2 = "\cxDesignation:\c-\n" "\cf Safety Tether\c-\n" @@ -3278,10 +3282,14 @@ SWWM_LORETXT_SAFETYTETHER2 = "\n" "What you see here is an extension of the magic employed in your \cfLucky Collar\c-, repurposed and adjusted to allow you to transport yourself on demand back to the entrance of the current area you're in. This is quite useful to have in case you find yourself trapped in some inescapable room, and have no other resources to break out. The world of \cfParthoris\c- is a treacherous one, as the \cfSidhe\c- would inform us, and so these are a must, and may be found in areas where \"trap rooms\" have been reported. It is assumed that \cfCronos\c- may feature the same sorts of traps, so be careful.\n" "\n" +"Simply twist both ends in opposing directions, and the device will prime. If the user is already standing close enough to the destination, the warp will be cancelled in order to prevent an accidental misuse, otherwise, the lights will turn blue and the warp will be performed.\n" +"\n" "\cxSaya's Notes:\c-\n" "\cfAh, the perfect way to escape from a closed room...\c-\n" "\n" -"\cfYeah, this is actually based on your collar, works similarly too, except I'm not the one who activates whenever you're in mortal danger, and its effects are more \"dramatic\" (you'll see). It's simple magic stuff, really. Those idiots at the UAC would shit themselves if they knew we've had the magic to do long distance teleports, even across universes, long before their experiments existed.\c-"; +"\cfYeah, this is actually based on your collar, works similarly too, except I'm not the one who activates whenever you're in mortal danger, and its effects are more \"dramatic\" (you'll see). It's simple magic stuff, really. Those idiots at the UAC would shit themselves if they knew we've had the magic to do long distance teleports, even across universes, long before their experiments existed.\c-\n" +"\n" +"\cfI hope Misa doesn't mind that I pretty much repurposed one of her grenade designs for this.\c-"; SWWM_LORETAG_SANKAIDERIHA = "Sankaideriha"; SWWM_LORETAB_SANKAIDERIHA = "Lore"; SWWM_LOREREL_SANKAIDERIHA = "Nukuri;Saya;Ashley;Gods;Kirin"; diff --git a/language.es_base b/language.es_base index e788ea4a5..9a163d8c1 100644 --- a/language.es_base +++ b/language.es_base @@ -538,6 +538,7 @@ D_FROGGY1 = "\cjUn pequeño precio a pagar...\c-"; D_FROGGY2 = "\cj... por una \cdSilla Rana\cj.\c-"; D_BARRIER = "El Revestimiento Elemental se ha desvanecido."; D_DEVASTATION = "El poder de la Marca se ha ido."; +D_TETHERFAIL = "El vínculo del Enlace de Seguridad fue obstruído."; D_MASHIRO = "\cjSabe donde estás...\c-"; SWWM_YNYKRONREADY = "Artefacto Ynykron listo para disparar."; SWWM_SWAPWEAPON = "\cjPulsa \cfUsar\cj para cambiar \cf%s\cj por \cf%s\cj.\c-"; diff --git a/language.es_lore b/language.es_lore index d8e457b5d..ad57de57f 100644 --- a/language.es_lore +++ b/language.es_lore @@ -3006,10 +3006,14 @@ SWWM_LORETXT_SAFETYTETHER = "\n" "Lo que ves aquí es una extensión de la magia empleada en tu \cfCollar de la Suerte\c-, reutilizada y ajustada para permitir transportarte a demanda de vuelta a la entrada del área actual en la que te encuentras. Es bastante útil tenerlo en caso de que te encuentres atrapada en una sala sin escapatoria, y no tengas otros recursos para abrirte paso. El mundo de \cfParthoris\c- es muy traicionero, tal como nos informaron los \cfSidhe\c-, por lo que estas son esenciales, y pueden encontrarse en zonas donde se reporta que hay \"habitaciones trampa\".\n" "\n" +"Simplemente gira ambos extremos en direcciones opuestas, y el dispositivo se encenderá. Si el usuario se encuentra ya cerca del punto de destino, el transporte será cancelado para evitar el uso accidental, de lo contrario, la luz se volverá azul y el transporte será realizado.\n" +"\n" "\cxNotas de Saya:\c-\n" "\cfAh, la forma perfecta de escapar una sala cerrada...\c-\n" "\n" -"\cfPues sí, esto está basado en tu collar, funciona parecido también, excepto que no soy yo quien lo activa cuando estás en peligro de muerte, y sus efectos son más \"dramáticos\" (ya lo verás). Es magia simple, realmente. Esos idiotas de la UAC se cagarían los calzones si supieran que hemos tenido la magia para hacer teletransportes distantes, hasta entre universos, mucho antes de que existieran sus experimentos.\c-"; +"\cfPues sí, esto está basado en tu collar, funciona parecido también, excepto que no soy yo quien lo activa cuando estás en peligro de muerte, y sus efectos son más \"dramáticos\" (ya lo verás). Es magia simple, realmente. Esos idiotas de la UAC se cagarían los calzones si supieran que hemos tenido la magia para hacer teletransportes distantes, hasta entre universos, mucho antes de que existieran sus experimentos.\c-\n" +"\n" +"\cfEspero que a Misa no le importe que haya reutilizado uno de sus diseños de granada para esto.\c-"; SWWM_LORETXT_SAFETYTETHER2 = "\cxDesignación:\c-\n" "\cf Enlace de Seguridad\c-\n" @@ -3021,10 +3025,14 @@ SWWM_LORETXT_SAFETYTETHER2 = "\n" "Lo que ves aquí es una extensión de la magia empleada en tu \cfCollar de la Suerte\c-, reutilizada y ajustada para permitir transportarte a demanda de vuelta a la entrada del área actual en la que te encuentras. Es bastante útil tenerlo en caso de que te encuentres atrapada en una sala sin escapatoria, y no tengas otros recursos para abrirte paso. El mundo de \cfParthoris\c- es muy traicionero, tal como nos informaron los \cfSidhe\c-, por lo que estas son esenciales, y pueden encontrarse en zonas donde se reporta que hay \"habitaciones trampa\". Cabe asumir que \cfCronos\c- tenga la misma clase de trampas, así que ten cuidado.\n" "\n" +"Simplemente gira ambos extremos en direcciones opuestas, y el dispositivo se encenderá. Si el usuario se encuentra ya cerca del punto de destino, el transporte será cancelado para evitar el uso accidental, de lo contrario, la luz se volverá azul y el transporte será realizado.\n" +"\n" "\cxNotas de Saya:\c-\n" "\cfAh, la forma perfecta de escapar una sala cerrada...\c-\n" "\n" -"\cfPues sí, esto está basado en tu collar, funciona parecido también, excepto que no soy yo quien lo activa cuando estás en peligro de muerte, y sus efectos son más \"dramáticos\" (ya lo verás). Es magia simple, realmente. Esos idiotas de la UAC se cagarían los calzones si supieran que hemos tenido la magia para hacer teletransportes distantes, hasta entre universos, mucho antes de que existieran sus experimentos.\c-"; +"\cfPues sí, esto está basado en tu collar, funciona parecido también, excepto que no soy yo quien lo activa cuando estás en peligro de muerte, y sus efectos son más \"dramáticos\" (ya lo verás). Es magia simple, realmente. Esos idiotas de la UAC se cagarían los calzones si supieran que hemos tenido la magia para hacer teletransportes distantes, hasta entre universos, mucho antes de que existieran sus experimentos.\c-\n" +"\n" +"\cfEspero que a Misa no le importe que haya reutilizado uno de sus diseños de granada para esto.\c-"; SWWM_LORETXT_SANKAIDERIHA = "\cxNombre:\c-\n" "\cf Sankaideriha (\"Capital de Magia\")\c-\n" diff --git a/language.version b/language.version index 44874fdfc..7be0dcd56 100644 --- a/language.version +++ b/language.version @@ -1,3 +1,3 @@ [default] -SWWM_MODVER="\chSWWM \czGZ\c- \cw1.1pre r1 \cu(Wed 1 Sep 18:53:53 CEST 2021)\c-"; -SWWM_SHORTVER="\cw1.1pre r1 \cu(2021-09-01 18:53:53)\c-"; +SWWM_MODVER="\chSWWM \czGZ\c- \cw1.1pre r2 \cu(Sat 4 Sep 21:18:37 CEST 2021)\c-"; +SWWM_SHORTVER="\cw1.1pre r2 \cu(2021-09-04 21:18:37)\c-"; diff --git a/lore/default/safetytether.txt b/lore/default/safetytether.txt index 9a0cacbd3..16dc21b78 100644 --- a/lore/default/safetytether.txt +++ b/lore/default/safetytether.txt @@ -3,7 +3,7 @@ Safety Tether TAB Item REL -AkariLabs;Cyrus;LuckyCollar;Parthoris;Sidhe;Cronos;Saya;UAC +AkariLabs;Cyrus;LuckyCollar;Parthoris;Sidhe;Cronos;Saya;UAC;Unissix TXT \cxDesignation:\c- \cf Safety Tether\c- @@ -15,10 +15,14 @@ TXT What you see here is an extension of the magic employed in your **Lucky Collar**, repurposed and adjusted to allow you to transport yourself on demand back to the entrance of the current area you're in. This is quite useful to have in case you find yourself trapped in some inescapable room, and have no other resources to break out. The world of **Parthoris** is a treacherous one, as the **Sidhe** would inform us, and so these are a must, and may be found in areas where "trap rooms" have been reported. +Simply twist both ends in opposing directions, and the device will prime. If the user is already standing close enough to the destination, the warp will be cancelled in order to prevent an accidental misuse, otherwise, the lights will turn blue and the warp will be performed. + \cxSaya's Notes:\c- \cfAh, the perfect way to escape from a closed room...\c- \cfYeah, this is actually based on your collar, works similarly too, except I'm not the one who activates whenever you're in mortal danger, and its effects are more "dramatic" (you'll see). It's simple magic stuff, really. Those idiots at the UAC would shit themselves if they knew we've had the magic to do long distance teleports, even across universes, long before their experiments existed.\c- + +\cfI hope Misa doesn't mind that I pretty much repurposed one of her grenade designs for this.\c- TXT \cxDesignation:\c- \cf Safety Tether\c- @@ -30,7 +34,11 @@ TXT What you see here is an extension of the magic employed in your **Lucky Collar**, repurposed and adjusted to allow you to transport yourself on demand back to the entrance of the current area you're in. This is quite useful to have in case you find yourself trapped in some inescapable room, and have no other resources to break out. The world of **Parthoris** is a treacherous one, as the **Sidhe** would inform us, and so these are a must, and may be found in areas where "trap rooms" have been reported. It is assumed that **Cronos** may feature the same sorts of traps, so be careful. +Simply twist both ends in opposing directions, and the device will prime. If the user is already standing close enough to the destination, the warp will be cancelled in order to prevent an accidental misuse, otherwise, the lights will turn blue and the warp will be performed. + \cxSaya's Notes:\c- \cfAh, the perfect way to escape from a closed room...\c- \cfYeah, this is actually based on your collar, works similarly too, except I'm not the one who activates whenever you're in mortal danger, and its effects are more "dramatic" (you'll see). It's simple magic stuff, really. Those idiots at the UAC would shit themselves if they knew we've had the magic to do long distance teleports, even across universes, long before their experiments existed.\c- + +\cfI hope Misa doesn't mind that I pretty much repurposed one of her grenade designs for this.\c- diff --git a/lore/es/safetytether.txt b/lore/es/safetytether.txt index 3695186e3..f24da66c1 100644 --- a/lore/es/safetytether.txt +++ b/lore/es/safetytether.txt @@ -11,10 +11,14 @@ TXT Lo que ves aquí es una extensión de la magia empleada en tu **Collar de la Suerte**, reutilizada y ajustada para permitir transportarte a demanda de vuelta a la entrada del área actual en la que te encuentras. Es bastante útil tenerlo en caso de que te encuentres atrapada en una sala sin escapatoria, y no tengas otros recursos para abrirte paso. El mundo de **Parthoris** es muy traicionero, tal como nos informaron los **Sidhe**, por lo que estas son esenciales, y pueden encontrarse en zonas donde se reporta que hay "habitaciones trampa". +Simplemente gira ambos extremos en direcciones opuestas, y el dispositivo se encenderá. Si el usuario se encuentra ya cerca del punto de destino, el transporte será cancelado para evitar el uso accidental, de lo contrario, la luz se volverá azul y el transporte será realizado. + \cxNotas de Saya:\c- \cfAh, la forma perfecta de escapar una sala cerrada...\c- \cfPues sí, esto está basado en tu collar, funciona parecido también, excepto que no soy yo quien lo activa cuando estás en peligro de muerte, y sus efectos son más "dramáticos" (ya lo verás). Es magia simple, realmente. Esos idiotas de la UAC se cagarían los calzones si supieran que hemos tenido la magia para hacer teletransportes distantes, hasta entre universos, mucho antes de que existieran sus experimentos.\c- + +\cfEspero que a Misa no le importe que haya reutilizado uno de sus diseños de granada para esto.\c- TXT \cxDesignación:\c- \cf Enlace de Seguridad\c- @@ -26,7 +30,11 @@ TXT Lo que ves aquí es una extensión de la magia empleada en tu **Collar de la Suerte**, reutilizada y ajustada para permitir transportarte a demanda de vuelta a la entrada del área actual en la que te encuentras. Es bastante útil tenerlo en caso de que te encuentres atrapada en una sala sin escapatoria, y no tengas otros recursos para abrirte paso. El mundo de **Parthoris** es muy traicionero, tal como nos informaron los **Sidhe**, por lo que estas son esenciales, y pueden encontrarse en zonas donde se reporta que hay "habitaciones trampa". Cabe asumir que **Cronos** tenga la misma clase de trampas, así que ten cuidado. +Simplemente gira ambos extremos en direcciones opuestas, y el dispositivo se encenderá. Si el usuario se encuentra ya cerca del punto de destino, el transporte será cancelado para evitar el uso accidental, de lo contrario, la luz se volverá azul y el transporte será realizado. + \cxNotas de Saya:\c- \cfAh, la forma perfecta de escapar una sala cerrada...\c- \cfPues sí, esto está basado en tu collar, funciona parecido también, excepto que no soy yo quien lo activa cuando estás en peligro de muerte, y sus efectos son más "dramáticos" (ya lo verás). Es magia simple, realmente. Esos idiotas de la UAC se cagarían los calzones si supieran que hemos tenido la magia para hacer teletransportes distantes, hasta entre universos, mucho antes de que existieran sus experimentos.\c- + +\cfEspero que a Misa no le importe que haya reutilizado uno de sus diseños de granada para esto.\c- diff --git a/modeldef.pickups b/modeldef.pickups index c30964fed..5b7c40940 100644 --- a/modeldef.pickups +++ b/modeldef.pickups @@ -301,16 +301,18 @@ Model "MykradvoX2" } Model "SafetyTether" { - Path "models/extra" + Path "models" - Model 0 "BaseCube_d.3d" - Skin 0 "CHIPTILE" - Scale 0.05 0.05 0.05 + Model 0 "SafetyTether_d.3d" + Skin 0 "SafetyTether_off.png" + Scale 0.02 0.02 0.02 ZOffset 16 PitchOffset 30 ROTATING FrameIndex XZW1 A 0 0 + Skin 0 "SafetyTether.png" + FrameIndex XZW1 B 0 0 } Model "AngerySigil" { diff --git a/models/SafetyTether.blend b/models/SafetyTether.blend new file mode 100644 index 000000000..6b6a8727e Binary files /dev/null and b/models/SafetyTether.blend differ diff --git a/models/SafetyTether.png b/models/SafetyTether.png new file mode 100644 index 000000000..ceb2c4e96 Binary files /dev/null and b/models/SafetyTether.png differ diff --git a/models/SafetyTether_a.3d b/models/SafetyTether_a.3d new file mode 100644 index 000000000..ce13e5e75 Binary files /dev/null and b/models/SafetyTether_a.3d differ diff --git a/models/SafetyTether_blue.png b/models/SafetyTether_blue.png new file mode 100644 index 000000000..3695cb17e Binary files /dev/null and b/models/SafetyTether_blue.png differ diff --git a/models/SafetyTether_bright.png b/models/SafetyTether_bright.png new file mode 100644 index 000000000..422127c28 Binary files /dev/null and b/models/SafetyTether_bright.png differ diff --git a/models/SafetyTether_d.3d b/models/SafetyTether_d.3d new file mode 100644 index 000000000..b43dfbbc4 Binary files /dev/null and b/models/SafetyTether_d.3d differ diff --git a/models/SafetyTether_mask.png b/models/SafetyTether_mask.png new file mode 100644 index 000000000..b7feb44b4 Binary files /dev/null and b/models/SafetyTether_mask.png differ diff --git a/models/SafetyTether_off.png b/models/SafetyTether_off.png new file mode 100644 index 000000000..b326c0668 Binary files /dev/null and b/models/SafetyTether_off.png differ diff --git a/models/SafetyTether_red.png b/models/SafetyTether_red.png new file mode 100644 index 000000000..008972df4 Binary files /dev/null and b/models/SafetyTether_red.png differ diff --git a/sndinfo.txt b/sndinfo.txt index 1b5390660..b319fede2 100644 --- a/sndinfo.txt +++ b/sndinfo.txt @@ -16,6 +16,7 @@ bruh sounds/BRUH.ogg squeak sounds/SQUEAK.ogg recordscratch sounds/RECSCRAP.ogg compat/warn sounds/UTWARN.ogg +hahaha/hahaha sounds/HAHAHA.ogg saya/giggle1 sounds/saya/saya_giggle1.ogg saya/giggle2 sounds/saya/saya_giggle2.ogg @@ -1036,6 +1037,8 @@ powerup/divineuse sounds/items/divion.ogg powerup/divineamb sounds/items/diviamb.ogg powerup/divineact sounds/items/diviact.ogg powerup/divineend sounds/items/diviend.ogg +powerup/tetheruse sounds/items/tetheruse.ogg +powerup/tetherfail sounds/items/tetherfail.ogg mykradvo/arc1 sounds/items/mykrarc1.ogg mykradvo/arc2 sounds/items/mykrarc2.ogg diff --git a/sounds/HAHAHA.ogg b/sounds/HAHAHA.ogg new file mode 100644 index 000000000..9f29a2db0 Binary files /dev/null and b/sounds/HAHAHA.ogg differ diff --git a/sounds/items/devaact.ogg b/sounds/items/devaact.ogg index b0f0bc852..665e55525 100644 Binary files a/sounds/items/devaact.ogg and b/sounds/items/devaact.ogg differ diff --git a/sounds/items/devahit.ogg b/sounds/items/devahit.ogg index 6128a4f81..ed9a2fcda 100644 Binary files a/sounds/items/devahit.ogg and b/sounds/items/devahit.ogg differ diff --git a/sounds/items/devaoff.ogg b/sounds/items/devaoff.ogg index 56f43357a..8b1ca1a5d 100644 Binary files a/sounds/items/devaoff.ogg and b/sounds/items/devaoff.ogg differ diff --git a/sounds/items/devaon.ogg b/sounds/items/devaon.ogg index 75d59028a..c83ffb902 100644 Binary files a/sounds/items/devaon.ogg and b/sounds/items/devaon.ogg differ diff --git a/sounds/items/tethererror.ogg b/sounds/items/tethererror.ogg new file mode 100644 index 000000000..03458653f Binary files /dev/null and b/sounds/items/tethererror.ogg differ diff --git a/sounds/items/tetherfail.ogg b/sounds/items/tetherfail.ogg new file mode 100644 index 000000000..06397bb9f Binary files /dev/null and b/sounds/items/tetherfail.ogg differ diff --git a/sounds/items/tetheruse.ogg b/sounds/items/tetheruse.ogg new file mode 100644 index 000000000..ff8838e8e Binary files /dev/null and b/sounds/items/tetheruse.ogg differ diff --git a/textcolors.txt b/textcolors.txt index 6b88e6761..a2eb7939e 100644 --- a/textcolors.txt +++ b/textcolors.txt @@ -48,3 +48,47 @@ Console: Flat: #9999FF } + +// VIP item colors +VIPPurple +{ + #230023 #7733FF +Console: + #000000 #7F009F 0 127 + #A000FF #FFFFFF 128 256 +Flat: + #7339E6 +} + +VIPGold +{ + #39264D #CC793D 0 127 + #CC793D #FFD580 128 256 +Console: + #39264D #CC793D 0 127 + #CC793D #FFD580 128 256 +Flat: + #CC793D +} + +VIPBrown +{ + #39264D #80593B 0 127 + #80593B #CCA37A 128 256 +Console: + #39264D #80593B 0 127 + #80593B #CCA37A 128 256 +Flat: + #80593B +} + +VIPTan +{ + #39264D #998B79 0 127 + #998B79 #E6CEB6 128 256 +Console: + #39264D #998B79 0 127 + #998B79 #E6CEB6 128 256 +Flat: + #998B79 +} diff --git a/zscript/dlc1/swwm_ammoitems_dlc.zsc b/zscript/dlc1/swwm_ammoitems_dlc.zsc index fc760ac4a..78003ab84 100644 --- a/zscript/dlc1/swwm_ammoitems_dlc.zsc +++ b/zscript/dlc1/swwm_ammoitems_dlc.zsc @@ -455,7 +455,7 @@ Class GrandAmmo : Ammo //$Icon ammo Tag "$T_GRANDAMMO"; Inventory.PickupMessage "$T_GRANDAMMO"; - Stamina 1200000; + Stamina -1200000; Inventory.Icon "graphics/HUD/Icons/A_GrandAmmo.png"; Inventory.Amount 1; Inventory.MaxAmount 1; diff --git a/zscript/dlc1/swwm_hugeassrailgun.zsc b/zscript/dlc1/swwm_hugeassrailgun.zsc index 841ff9136..bb142fec6 100644 --- a/zscript/dlc1/swwm_hugeassrailgun.zsc +++ b/zscript/dlc1/swwm_hugeassrailgun.zsc @@ -29,7 +29,7 @@ Class GrandLance : SWWMWeapon SWWMWeapon.DropAmmoType "GrandAmmo"; GrandLance.ClipCount 5; GrandLance.ClipCount2 500; - Stamina 4200000; + Stamina -4200000; +SWWMWEAPON.NOFIRSTGIVE; +WEAPON.PRIMARY_USES_BOTH; +WEAPON.EXPLOSIVE; diff --git a/zscript/dlc2/swwm_ammoitems_dlc2.zsc b/zscript/dlc2/swwm_ammoitems_dlc2.zsc index 4bcd3f24e..ab7a3933a 100644 --- a/zscript/dlc2/swwm_ammoitems_dlc2.zsc +++ b/zscript/dlc2/swwm_ammoitems_dlc2.zsc @@ -282,7 +282,7 @@ Class UltimateAmmo : Ammo //$Icon ammo Tag "$T_ULTIMATEAMMO"; Inventory.PickupMessage "$T_ULTIMATEAMMO"; - Stamina 2000000; + Stamina -2000000; Inventory.Icon "graphics/HUD/Icons/A_UltimateAmmo.png"; Inventory.Amount 1; Inventory.MaxAmount 1; diff --git a/zscript/dlc2/swwm_ultimate.zsc b/zscript/dlc2/swwm_ultimate.zsc index 7ee70860d..04e6407f4 100644 --- a/zscript/dlc2/swwm_ultimate.zsc +++ b/zscript/dlc2/swwm_ultimate.zsc @@ -25,7 +25,7 @@ Class RafanKos : SWWMWeapon Weapon.AmmoGive1 1; SWWMWeapon.DropAmmoType "UltimateAmmo"; RafanKos.ClipCount 4; - Stamina 5000000; + Stamina -5000000; +SWWMWEAPON.NOFIRSTGIVE; +WEAPON.EXPLOSIVE; +WEAPON.BFG; diff --git a/zscript/handler/swwm_handler_cheats.zsc b/zscript/handler/swwm_handler_cheats.zsc index 1ce890465..49cb2c482 100644 --- a/zscript/handler/swwm_handler_cheats.zsc +++ b/zscript/handler/swwm_handler_cheats.zsc @@ -60,7 +60,7 @@ extend Class SWWMHandler Vector3 safepos; double safeangle; [safepos, safeangle] = level.PickPlayerStart(e.Args[0]); - players[e.Args[0]].mo.Teleport(safepos,safeangle,TF_TELEFRAG|TF_FORCED|TF_USESPOTZ); + players[e.Args[0]].mo.Teleport(safepos,safeangle,0); } else if ( e.Name ~== "swwmweaponcheat" ) { diff --git a/zscript/items/swwm_ammoitems.zsc b/zscript/items/swwm_ammoitems.zsc index 6390efde6..a1afe59ed 100644 --- a/zscript/items/swwm_ammoitems.zsc +++ b/zscript/items/swwm_ammoitems.zsc @@ -1186,7 +1186,7 @@ Class YnykronAmmo : Ammo //$Icon ammo Tag "$T_YNYKRONAMMO"; Inventory.PickupMessage "$T_YNYKRONAMMO"; - Stamina 3000000; + Stamina -3000000; Inventory.Icon "graphics/HUD/Icons/A_Ynykron.png"; Inventory.Amount 1; Inventory.MaxAmount 1; diff --git a/zscript/items/swwm_basearmor.zsc b/zscript/items/swwm_basearmor.zsc index e08c0b065..e1d843187 100644 --- a/zscript/items/swwm_basearmor.zsc +++ b/zscript/items/swwm_basearmor.zsc @@ -97,7 +97,7 @@ Class SWWMArmor : Armor abstract if ( (amount <= 0) || DamageTypeDefinition.IgnoreArmor(damageType) || (damage <= 0) ) return; SWWMHandler.DoFlash(Owner,Color(int(clamp(damage*.15,1,16)),255,224,192),3); - Owner.A_StartSound("armor/hit",CHAN_BODY,CHANF_DEFAULT,clamp(damage*.03,0.,1.),2.5); + Owner.A_StartSound("armor/hit",CHAN_DAMAGE,CHANF_OVERLAP,clamp(damage*.03,0.,1.),2.5); saved = HandleDamage(damage,damageType,flags); int healed = max(0,saved-damage); saved = min(saved,damage); @@ -117,7 +117,7 @@ Class SWWMArmor : Armor abstract else shouldautouse = CVar.GetCVar('swwm_autousearmor',Owner.player).GetBool(); if ( (amount <= (MaxAmount-default.Amount)) && (Owner.CountInv(parent) > 0) && shouldautouse ) { - if ( GetDefaultByType(parent).UseSound ) Owner.A_StartSound(GetDefaultByType(parent).UseSound,CHAN_ITEMEXTRA,CHANF_DEFAULT,.6); + if ( GetDefaultByType(parent).UseSound ) Owner.A_StartSound(GetDefaultByType(parent).UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP,.6); int tgive = 0; while ( (amount <= (MaxAmount-default.Amount)) && (Owner.CountInv(parent) > 0) ) { @@ -164,7 +164,7 @@ Class SWWMSpareArmor : Inventory abstract let cur = Owner.FindInventory(giveme); if ( !cur || (!pickup && (cur.Amount < cur.MaxAmount)) || (GetDefaultByType(giveme).Amount+cur.Amount <= cur.MaxAmount) ) { - if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); + if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); Owner.GiveInventory(giveme,GetDefaultByType(giveme).Amount); SWWMHandler.ArmorFlash(Owner.PlayerNumber()); SWWMScoreObj.Spawn(GetDefaultByType(giveme).Amount,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Armor); diff --git a/zscript/items/swwm_basehealth.zsc b/zscript/items/swwm_basehealth.zsc index c6756a5d1..c99de2e05 100644 --- a/zscript/items/swwm_basehealth.zsc +++ b/zscript/items/swwm_basehealth.zsc @@ -128,7 +128,7 @@ Class SWWMHealth : Inventory abstract let hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); if ( hnd ) hnd.tookdamage[Owner.PlayerNumber()] = true; } - if ( ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); + if ( ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); int tgive = 0; bool morethanonce = false; while ( (Amount > 0) && (newdamage > 0) ) diff --git a/zscript/items/swwm_health.zsc b/zscript/items/swwm_health.zsc index 61053bc95..d8e529f9d 100644 --- a/zscript/items/swwm_health.zsc +++ b/zscript/items/swwm_health.zsc @@ -57,7 +57,7 @@ Class RefresherRegen : Powerup if ( !Owner.GiveBody(int(Strength),500) ) return; SWWMScoreObj.Spawn(int(Strength),Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health); SWWMHandler.DoFlash(Owner,Color(32,224,128,255),10); - Owner.A_StartSound("powerup/refresher",CHAN_ITEM,CHANF_LOCAL,.4); + Owner.A_StartSound("powerup/refresher",CHAN_ITEMEXTRA,CHANF_LOCAL|CHANF_OVERLAP,.4); if ( Owner is 'Demolitionist' ) Demolitionist(Owner).lastbump *= 0.99; } diff --git a/zscript/items/swwm_powerups.zsc b/zscript/items/swwm_powerups.zsc index db1543ed4..5a32a145c 100644 --- a/zscript/items/swwm_powerups.zsc +++ b/zscript/items/swwm_powerups.zsc @@ -86,7 +86,7 @@ Class GrilledCheeseSandwich : Inventory { if ( pickup && !deathmatch ) return false; if ( Owner.Health > 500 ) return false; - if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); + if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); DoTheThing(); return true; } @@ -115,7 +115,7 @@ Class GrilledCheeseSandwich : Inventory if ( damageType == 'InstantDeath' ) SafeTeleport(); // get out of pits newdamage = 0; - if ( (Owner.player == players[consoleplayer]) || bBigPowerup ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); + if ( (Owner.player == players[consoleplayer]) || bBigPowerup ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); DoTheThing(true); Amount--; } @@ -135,7 +135,7 @@ Class GrilledCheeseSandwich : Inventory safepos = lastsafepos[4]; safeangle = lastsafeangle[4]; } - Owner.Teleport(safepos,safeangle,TF_TELEFRAG|TF_FORCED|TF_USESPOTZ|TF_NOFOG); + Owner.Teleport(safepos,safeangle,0); } override void DoEffect() { @@ -360,7 +360,7 @@ Class GhostPower : PowerInvisibility { Super.EndEffect(); if ( !Owner ) return; - Owner.A_StartSound("powerup/ghostend",CHAN_ITEMEXTRA); + Owner.A_StartSound("powerup/ghostend",CHAN_ITEMEXTRA,CHANF_OVERLAP); SWWMHandler.DoFlash(Owner,Color(96,224,192,255),20); if ( Owner is 'Demolitionist' ) Demolitionist(Owner).lastbump *= 1.02; @@ -484,7 +484,7 @@ Class GhostArtifact : Inventory override bool Use( bool pickup ) { if ( pickup && !deathmatch ) return false; - if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); + if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); let g = GhostPower(Owner.FindInventory("GhostPower")); if ( g ) { @@ -598,7 +598,7 @@ Class GravityPower : Powerup Owner.bNOGRAVITY = false; if ( Owner.pos.z > Owner.floorz ) Owner.player.centering = true; } - Owner.A_StartSound("powerup/gravityend",CHAN_ITEMEXTRA); + Owner.A_StartSound("powerup/gravityend",CHAN_ITEMEXTRA,CHANF_OVERLAP); if ( Owner is 'Demolitionist' ) Demolitionist(Owner).lastbump *= 1.02; if ( (EffectTics <= 0) && Owner && Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_GRAVITYS")); @@ -636,7 +636,7 @@ Class GravitySuppressor : Inventory override bool Use( bool pickup ) { if ( pickup && !deathmatch ) return false; - if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); + if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); let g = GravityPower(Owner.FindInventory("GravityPower")); if ( g ) { @@ -804,7 +804,7 @@ Class InvinciballPower : Powerup { Super.EndEffect(); if ( !Owner ) return; - Owner.A_StartSound("powerup/invinciballend",CHAN_ITEMEXTRA); + Owner.A_StartSound("powerup/invinciballend",CHAN_ITEMEXTRA,CHANF_OVERLAP); SWWMHandler.DoFlash(Owner,Color(96,255,64,0),20); if ( Owner is 'Demolitionist' ) Demolitionist(Owner).lastbump *= 1.05; @@ -846,7 +846,7 @@ Class InvinciballPower : Powerup if ( level.maptime > lasteffect+5 ) { SWWMHandler.DoFlash(Owner,Color(64,255,64,0),15); - Owner.A_StartSound("powerup/invinciballhit",CHAN_POWERUP); + Owner.A_StartSound("powerup/invinciballhit",CHAN_POWERUP,CHANF_OVERLAP); lasteffect = level.maptime; lastpulse = max(lastpulse,gametic+20); if ( Owner is 'Demolitionist' ) @@ -881,7 +881,7 @@ Class FuckingInvinciball : Inventory override bool Use( bool pickup ) { if ( pickup && !deathmatch ) return false; - if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); + if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); Owner.A_StartSound("misc/sundowner",CHAN_POWERUPEXTRA); let i = InvinciballPower(Owner.FindInventory("InvinciballPower")); if ( i ) @@ -1079,7 +1079,7 @@ Class RagekitPower : Powerup { Super.EndEffect(); if ( !Owner ) return; - Owner.A_StartSound("powerup/ragekitend",CHAN_ITEMEXTRA); + Owner.A_StartSound("powerup/ragekitend",CHAN_ITEMEXTRA,CHANF_OVERLAP); SWWMHandler.DoFlash(Owner,Color(128,255,0,0),30); Owner.A_QuakeEx(4,4,4,20,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:1.); Owner.A_AlertMonsters(2000); @@ -1120,7 +1120,7 @@ Class RagekitPower : Powerup Owner.A_QuakeEx(8,8,8,Random[Rage](3,8),0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:1.); if ( (Owner.player == players[consoleplayer]) && (gametic > lastrage) && (swwm_mutevoice < 2) ) lastrage = SWWMHandler.AddOneliner("ragekit",2,5)+40; - Owner.A_StartSound("powerup/ragekithit",CHAN_POWERUP); + Owner.A_StartSound("powerup/ragekithit",CHAN_POWERUP,CHANF_OVERLAP); lasteffect = level.maptime; lastpulse = max(lastpulse,gametic+35); Demolitionist(Owner).lastbump *= .9; @@ -1250,7 +1250,7 @@ Class Omnisight : Inventory { if ( Owner.player == players[consoleplayer] ) { - Owner.A_StartSound("powerup/omnisight",CHAN_ITEMEXTRA); + Owner.A_StartSound("powerup/omnisight",CHAN_ITEMEXTRA,CHANF_OVERLAP); // automatically zoom out so the player can know how far this goes CVar.FindCVar('swwm_mm_zoom').SetFloat(2.); } @@ -1268,7 +1268,7 @@ Class Omnisight : Inventory if ( i == consoleplayer ) { Console.Printf(StringTable.Localize("$D_OMNISHARE"),Owner.player.GetUserName()); - players[i].mo.A_StartSound("powerup/omnisight",CHAN_ITEMEXTRA); + players[i].mo.A_StartSound("powerup/omnisight",CHAN_ITEMEXTRA,CHANF_OVERLAP); // automatically zoom out so the player can know how far this goes CVar.FindCVar('swwm_mm_zoom').SetFloat(2.); } @@ -1843,7 +1843,7 @@ Class CompanionLamp : Actor { if ( SWWMLamp(master) && SWWMLamp(master).bActive ) { - A_StartSound("lamp/on",CHAN_ITEMEXTRA); + A_StartSound("lamp/on",CHAN_ITEMEXTRA,CHANF_OVERLAP); return ResolveState("Active"); } return ResolveState(null); @@ -1855,7 +1855,7 @@ Class CompanionLamp : Actor A_Moth(); if ( !SWWMLamp(master) || !SWWMLamp(master).bActive ) { - A_StartSound("lamp/off",CHAN_ITEMEXTRA); + A_StartSound("lamp/off",CHAN_ITEMEXTRA,CHANF_OVERLAP); return ResolveState("Spawn"); } return ResolveState(null); @@ -2126,7 +2126,7 @@ Class BarrierPower : PowerIronFeet { Super.EndEffect(); if ( !Owner ) return; - Owner.A_StartSound("powerup/barrierend",CHAN_ITEMEXTRA); + Owner.A_StartSound("powerup/barrierend",CHAN_ITEMEXTRA,CHANF_OVERLAP); if ( Owner is 'Demolitionist' ) Demolitionist(Owner).lastbump *= 0.95; if ( (EffectTics <= 0) && Owner && Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$D_BARRIER")); @@ -2154,7 +2154,7 @@ Class EBarrier : Inventory override bool Use( bool pickup ) { if ( pickup && !deathmatch ) return false; - if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); + if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); let b = BarrierPower(Owner.FindInventory("BarrierPower")); if ( b ) { @@ -2760,7 +2760,7 @@ Class Mykradvo : Inventory override bool Use( bool pickup ) { if ( pickup && !deathmatch ) return false; - if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); + if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); Vector3 spawnpos = Owner.Vec3Angle(15,Owner.angle,Owner.Height*.7); if ( !FindTargets(Owner) ) { @@ -2807,7 +2807,7 @@ Class Mykradvo : Inventory s.pitch = pt; s.ReactionTime += Random[ExploS](-2,2); } - A_StartSound("mykradvo/smallarc",CHAN_WEAPON,attenuation:3.); + A_StartSound("mykradvo/smallarc",CHAN_WEAPON,CHANF_OVERLAP,attenuation:3.); A_SetTics(Random[Mykradvo](10,50)); } @@ -2872,7 +2872,7 @@ Class Mykradvo : Inventory //$Sprite graphics/HUD/Icons/I_Mykradvo.png //$Icon powerup Tag "$T_MYKRADVO"; - Stamina 1200000; + Stamina -1200000; Inventory.Icon "graphics/HUD/Icons/I_Mykradvo.png"; Inventory.PickupSound "misc/p_pkup"; Inventory.UseSound "mykradvo/arc"; @@ -2979,7 +2979,91 @@ Class SafetyTether : Inventory Mixin SWWMOverlapPickupSound; Mixin SWWMUseToPickup; Mixin SWWMRespawn; - Mixin SWWMPickupGlow; + + bool bPrimed, bFailed; + int primetim; + TextureID OnIcon[3]; + + override void Travelled() + { + Super.Travelled(); + bPrimed = false; + } + override Inventory CreateTossable( int amt ) + { + if ( bPrimed ) return null; // can't drop while primed + let ret = Super.CreateTossable(amt); + // reattach our glow if we became a pickup + if ( (ret == self) && (PickupFlash is 'SWWMPickupFlash') && swwm_itemglows ) + { + let p = Spawn(PickupFlash,Vec3Offset(0,0,16)); + p.target = self; + p.SetStateLabel("Pickup"); + } + return ret; + } + + override void DoEffect() + { + Super.DoEffect(); + if ( !bPrimed ) return; + Icon = ((primetim%4)>=2)?default.Icon:(primetim>=6)?(bFailed?OnIcon[1]:OnIcon[2]):OnIcon[0]; + if ( !bFailed && (primetim == 20) ) Owner.A_StartSound("hahaha/hahaha",CHAN_POWERUP,CHANF_OVERLAP); + primetim++; + if ( (primetim <= 20) || (!bFailed && (primetim <= 50)) ) return; + primetim = 0; + bPrimed = false; + Icon = default.Icon; + if ( bFailed ) return; + Vector3 safepos; + double safeangle; + if ( deathmatch ) [safepos, safeangle] = level.PickDeathmatchStart(); + else [safepos, safeangle] = level.PickPlayerStart(Owner.PlayerNumber()); + Vector3 oldpos = Owner.pos; + if ( !Owner.Teleport(safepos,safeangle,0) ) + { + if ( Owner is 'Demolitionist' ) + Demolitionist(Owner).lastbump *= .95; + Owner.A_StartSound("powerup/tethererror",CHAN_ITEMEXTRA,CHANF_OVERLAP); + if ( Owner.player == players[consoleplayer] ) Console.Printf(StringTable.Localize("$D_TETHERFAIL")); + return; + } + let s = Spawn("DemolitionistShockwave",oldpos); + s.target = Owner; + s.special1 = 120; + s = Spawn("DemolitionistShockwave",Owner.pos); + s.target = Owner; + s.special1 = 120; + if ( Owner.player == players[consoleplayer] ) + { + Owner.A_StartSound("demolitionist/hardland",CHAN_FOOTSTEP,CHANF_OVERLAP); + Owner.A_StartSound("demolitionist/hardland",CHAN_FOOTSTEP,CHANF_OVERLAP,pitch:.7); + Owner.A_StartSound("demolitionist/hardland",CHAN_FOOTSTEP,CHANF_OVERLAP,pitch:.4); + } + SWWMHandler.DoFlash(Owner,Color(255,255,255,255),10); + SWWMHandler.DoFlash(Owner,Color(255,128,192,255),30); + SWWMUtility.AchievementProgressInc('swwm_progress_sneaky',1,Owner.player); + Amount--; + if ( Amount <= 0 ) DepleteOrDestroy(); + } + + override bool Use( bool pickup ) + { + if ( pickup || bPrimed ) return false; + if ( !OnIcon[0] ) OnIcon[0] = TexMan.CheckForTexture("graphics/HUD/Icons/I_SafetyOn.png"); + if ( !OnIcon[1] ) OnIcon[1] = TexMan.CheckForTexture("graphics/HUD/Icons/I_SafetyNo.png"); + if ( !OnIcon[2] ) OnIcon[2] = TexMan.CheckForTexture("graphics/HUD/Icons/I_SafetyYes.png"); + bPrimed = true; + primetim = 0; + Vector3 safepos; + if ( deathmatch ) safepos = level.PickDeathmatchStart(); + else safepos = level.PickPlayerStart(Owner.PlayerNumber()); + bFailed = (level.Vec3Diff(Owner.pos,safepos).length() < 400); + if ( (Owner.player == players[consoleplayer]) || bBigPowerup ) Owner.A_StartSound(bFailed?"powerup/tetherfail":"powerup/tetheruse",CHAN_ITEMEXTRA,CHANF_OVERLAP); + // don't consume on use, will happen later + Amount++; + return true; + } Default { @@ -2988,10 +3072,10 @@ Class SafetyTether : Inventory //$Sprite graphics/HUD/Icons/I_Safety.png //$Icon powerup Tag "$T_SAFETY"; - Stamina 160000; + Stamina 240000; Inventory.Icon "graphics/HUD/Icons/I_Safety.png"; Inventory.PickupSound "misc/p_pkup"; - Inventory.UseSound "powerup/safety"; + Inventory.UseSound ""; Inventory.PickupMessage "$T_SAFETY"; Inventory.MaxAmount 5; Inventory.InterHubAmount 5; @@ -3003,12 +3087,15 @@ Class SafetyTether : Inventory +INVENTORY.BIGPOWERUP; +FLOATBOB; FloatBobStrength 0.25; + Radius 5; + Height 23; } States { Spawn: - XZW1 A -1; - Stop; + XZW1 A 33; + XZW1 B 2; + Loop; } } @@ -3115,7 +3202,7 @@ Class AngeryPower : Powerup { Super.EndEffect(); if ( !Owner ) return; - Owner.A_StartSound("powerup/devastationend",CHAN_ITEMEXTRA); + Owner.A_StartSound("powerup/devastationend",CHAN_ITEMEXTRA,CHANF_OVERLAP); SWWMHandler.DoFlash(Owner,Color(128,224,0,255),30); Owner.A_QuakeEx(4,4,4,20,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:1.); Owner.A_AlertMonsters(2000); @@ -3130,7 +3217,7 @@ Class AngeryPower : Powerup Owner.A_AlertMonsters(swwm_uncapalert?0:5000); SWWMHandler.DoFlash(Owner,Color(64,224,0,255),10); Owner.A_QuakeEx(8,8,8,Random[Rage](3,8),0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:1.); - Owner.A_StartSound("powerup/devastationhit",CHAN_POWERUP); + Owner.A_StartSound("powerup/devastationhit",CHAN_POWERUP,CHANF_OVERLAP); lasteffect = level.maptime; lastpulse = max(lastpulse,gametic+35); if ( Owner is 'Demolitionist' ) @@ -3157,7 +3244,7 @@ Class AngerySigil : Inventory override bool Use( bool pickup ) { if ( pickup && !deathmatch ) return false; - if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); + if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); SWWMUtility.AchievementProgressInc('swwm_progress_deva',1,Owner.player); let r = AngeryPower(Owner.FindInventory("AngeryPower")); if ( r ) @@ -3197,7 +3284,7 @@ Class AngerySigil : Inventory //$Sprite graphics/HUD/Icons/I_Devastation.png //$Icon powerup Tag "$T_DEVASTATION"; - Stamina 1500000; + Stamina -1500000; Inventory.Icon "graphics/HUD/Icons/I_Devastation.png"; Inventory.PickupSound "misc/p_pkup"; Inventory.UseSound "powerup/devastation"; @@ -3387,7 +3474,7 @@ Class DivineSpriteEffect : Inventory healtim--; if ( (healtim <= 0) || (Owner.Health <= 0) ) { - Owner.A_StartSound("powerup/divineend",CHAN_ITEMEXTRA); + Owner.A_StartSound("powerup/divineend",CHAN_ITEMEXTRA,CHANF_OVERLAP); SWWMHandler.DoFlash(Owner,Color(80,255,255,255),40); if ( Owner is 'Demolitionist' ) Demolitionist(Owner).lastbump *= 0.95; @@ -3401,14 +3488,14 @@ Class DivineSpriteEffect : Inventory SWWMHandler.DoFlash(Owner,Color(40,255,255,255),20); if ( Owner is 'Demolitionist' ) Demolitionist(Owner).lastbump *= 0.97; - Owner.A_StartSound("powerup/divinehit",CHAN_ITEMEXTRA); + Owner.A_StartSound("powerup/divinehit",CHAN_ITEMEXTRA,CHANF_OVERLAP); } else if ( !(healcnt%5) ) { Owner.GiveBody(500,10000); SWWMScoreObj.Spawn(100,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health); SWWMHandler.DoFlash(Owner,Color(10,255,255,255),10); - Owner.A_StartSound("powerup/divinehit",CHAN_ITEMEXTRA); + Owner.A_StartSound("powerup/divinehit",CHAN_ITEMEXTRA,CHANF_OVERLAP); } } } @@ -3426,7 +3513,7 @@ Class DivineSprite : Inventory if ( pickup && !deathmatch ) return false; let p = Owner.FindInventory("DivineSpriteEffect"); if ( p ) return false; - if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); + if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); Owner.GiveInventory("DivineSpriteEffect",1); SWWMUtility.AchievementProgressInc('swwm_progress_divine',1,Owner.player); return true; @@ -3458,7 +3545,7 @@ Class DivineSprite : Inventory //$Sprite graphics/HUD/Icons/I_Divine.png //$Icon powerup Tag "$T_DIVINE"; - Stamina 3600000; + Stamina -3600000; Inventory.Icon "graphics/HUD/Icons/I_Divine.png"; Inventory.PickupSound "misc/p_pkup"; Inventory.UseSound "powerup/divineuse"; diff --git a/zscript/kbase/swwm_kbase.zsc b/zscript/kbase/swwm_kbase.zsc index 12ff70fd9..221db3534 100644 --- a/zscript/kbase/swwm_kbase.zsc +++ b/zscript/kbase/swwm_kbase.zsc @@ -3203,15 +3203,14 @@ Class DemolitionistMenu : GenericMenu else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && !(invlist[i] is 'Weapon') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); else str = invlist[i].GetTag(); int clscol = Font.CR_WHITE; - if ( invlist[i] is 'Weapon' ) clscol = Font.CR_GOLD; - else if ( invlist[i] is 'MagAmmo' ) clscol = Font.CR_TAN; + if ( invlist[i] is 'Weapon' ) clscol = SWWMUtility.IsVIPItem(invlist[i])?Font.FindFontColor('VIPGold'):Font.CR_GOLD; + else if ( invlist[i] is 'MagAmmo' ) clscol = SWWMUtility.IsVIPItem(invlist[i])?Font.FindFontColor('VIPTan'):Font.CR_TAN; else if ( (invlist[i] is 'BackpackItem') || (invlist[i] is 'HammerspaceEmbiggener') ) clscol = Font.CR_DARKBROWN; - else if ( invlist[i] is 'Ammo' ) clscol = Font.CR_BROWN; - else if ( (invlist[i] is 'PowerupGiver') || (invlist[i] is 'AmmoFabricator') || invlist[i].bBIGPOWERUP ) clscol = Font.CR_PURPLE; + else if ( invlist[i] is 'Ammo' ) clscol = SWWMUtility.IsVIPItem(invlist[i])?Font.FindFontColor('VIPBrown'):Font.CR_BROWN; + else if ( (invlist[i] is 'PowerupGiver') || (invlist[i] is 'AmmoFabricator') || invlist[i].bBIGPOWERUP ) clscol = SWWMUtility.IsVIPItem(invlist[i])?Font.FindFontColor('VIPPurple'):Font.CR_PURPLE; else if ( (invlist[i] is 'Health') || (invlist[i] is 'HealthPickup') || (invlist[i] is 'SWWMHealth') ) clscol = Font.CR_RED; else if ( (invlist[i] is 'Armor') || (invlist[i] is 'SWWMSpareArmor') ) clscol = Font.CR_GREEN; else if ( invlist[i] is 'PuzzleItem' ) clscol = Font.CR_LIGHTBLUE; - else if ( invlist[i] is 'SWWMCollectible' ) clscol = Font.CR_FIRE; Screen.DrawText(fnt,clscol,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(96,0,0,0):Color(0,0,0,0)); yy += 16; if ( yy >= 370 ) @@ -3263,15 +3262,14 @@ Class DemolitionistMenu : GenericMenu else if ( (invlist[i].Amount > 1) || (!(invlist[i] is 'PuzzleItem') && !(invlist[i] is 'Weapon') && (invlist[i].MaxAmount > 1)) ) str = String.Format("%dx %s",invlist[i].Amount,invlist[i].GetTag()); else str = invlist[i].GetTag(); int clscol = Font.CR_WHITE; - if ( invlist[i] is 'Weapon' ) clscol = Font.CR_GOLD; - else if ( invlist[i] is 'MagAmmo' ) clscol = Font.CR_TAN; + if ( invlist[i] is 'Weapon' ) clscol = SWWMUtility.IsVIPItem(invlist[i])?Font.FindFontColor('VIPGold'):Font.CR_GOLD; + else if ( invlist[i] is 'MagAmmo' ) clscol = SWWMUtility.IsVIPItem(invlist[i])?Font.FindFontColor('VIPTan'):Font.CR_TAN; else if ( (invlist[i] is 'BackpackItem') || (invlist[i] is 'HammerspaceEmbiggener') ) clscol = Font.CR_DARKBROWN; - else if ( invlist[i] is 'Ammo' ) clscol = Font.CR_BROWN; - else if ( (invlist[i] is 'PowerupGiver') || (invlist[i] is 'AmmoFabricator') || invlist[i].bBIGPOWERUP ) clscol = Font.CR_PURPLE; + else if ( invlist[i] is 'Ammo' ) clscol = SWWMUtility.IsVIPItem(invlist[i])?Font.FindFontColor('VIPBrown'):Font.CR_BROWN; + else if ( (invlist[i] is 'PowerupGiver') || (invlist[i] is 'AmmoFabricator') || invlist[i].bBIGPOWERUP ) clscol = SWWMUtility.IsVIPItem(invlist[i])?Font.FindFontColor('VIPPurple'):Font.CR_PURPLE; else if ( (invlist[i] is 'Health') || (invlist[i] is 'HealthPickup') || (invlist[i] is 'SWWMHealth') ) clscol = Font.CR_RED; else if ( (invlist[i] is 'Armor') || (invlist[i] is 'SWWMSpareArmor') ) clscol = Font.CR_GREEN; else if ( invlist[i] is 'PuzzleItem' ) clscol = Font.CR_LIGHTBLUE; - else if ( invlist[i] is 'SWWMCollectible' ) clscol = Font.CR_FIRE; Screen.DrawText(fnt,clscol,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel1)?Color(96,0,0,0):Color(0,0,0,0)); yy += 16; if ( yy >= 370 ) @@ -3464,11 +3462,11 @@ Class DemolitionistMenu : GenericMenu else if ( (storeunits[i] > 1) || (storelist[i] is 'Ammo') ) str = String.Format("%dx %s",storeunits[i],def.GetTag()); else str = def.GetTag(); int clscol = Font.CR_WHITE; - if ( storelist[i] is 'Weapon' ) clscol = Font.CR_GOLD; - else if ( storelist[i] is 'MagAmmo' ) clscol = Font.CR_TAN; + if ( storelist[i] is 'Weapon' ) clscol = SWWMUtility.IsVIPItemClass(storelist[i])?Font.FindFontColor('VIPGold'):Font.CR_GOLD; + else if ( storelist[i] is 'MagAmmo' ) clscol = SWWMUtility.IsVIPItemClass(storelist[i])?Font.FindFontColor('VIPTan'):Font.CR_TAN; else if ( (storelist[i] is 'BackpackItem') || (storelist[i] is 'HammerspaceEmbiggener') ) clscol = Font.CR_DARKBROWN; - else if ( storelist[i] is 'Ammo' ) clscol = Font.CR_BROWN; - else if ( (storelist[i] is 'PowerupGiver') || (storelist[i] is 'AmmoFabricator') || def.bBIGPOWERUP ) clscol = Font.CR_PURPLE; + else if ( storelist[i] is 'Ammo' ) clscol = SWWMUtility.IsVIPItemClass(storelist[i])?Font.FindFontColor('VIPBrown'):Font.CR_BROWN; + else if ( (storelist[i] is 'PowerupGiver') || (storelist[i] is 'AmmoFabricator') || def.bBIGPOWERUP ) clscol = SWWMUtility.IsVIPItemClass(storelist[i])?Font.FindFontColor('VIPPurple'):Font.CR_PURPLE; else if ( (storelist[i] is 'Health') || (storelist[i] is 'HealthPickup') || (storelist[i] is 'SWWMHealth') ) clscol = Font.CR_RED; else if ( (storelist[i] is 'Armor') || (storelist[i] is 'SWWMSpareArmor') ) clscol = Font.CR_GREEN; Screen.DrawText(fnt,clscol,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_ColorOverlay,(i!=sel0)?Color(96,0,0,0):Color(0,0,0,0)); diff --git a/zscript/swwm_player.zsc b/zscript/swwm_player.zsc index eaaeebb54..60c1c4811 100644 --- a/zscript/swwm_player.zsc +++ b/zscript/swwm_player.zsc @@ -173,7 +173,7 @@ Class Demolitionist : PlayerPawn let type = (class)(AllActorClasses[i]); if ( !type || (type.GetParentClass() != "Ammo") ) continue; - // Only give if it's for a valid weapon, unless using "give everything" + // Only give if it's for a valid weapon bool isvalid = false; for ( int j=0; j)(AllActorClasses[j]); - if ( !type2 ) continue; - let rep = GetReplacement(type2); - if ( (rep != type2) && !(rep is "DehackedPickup") ) continue; - readonly weap = GetDefaultByType(type2); - if ( !player.weapons.LocateWeapon(type2) || weap.bCheatNotWeapon || !weap.CanPickup(self) ) continue; - let ready = weap.FindState("Ready"); - if ( !ready || !ready.ValidateSpriteFrame() ) continue; - if ( (type2 is 'SWWMWeapon') && SWWMWeapon(weap).UsesAmmo(pamo) ) + readonly weap = GetDefaultByType(validweapons[j]); + if ( (validweapons[j] is 'SWWMWeapon') && SWWMWeapon(weap).UsesAmmo(pamo) ) { isvalid = true; break; @@ -230,7 +223,7 @@ Class Demolitionist : PlayerPawn break; } } - if ( !isvalid && (giveall != ALL_YESYES) ) continue; + if ( !isvalid ) continue; let magitem = FindInventory(type); if ( !magitem ) { @@ -341,6 +334,9 @@ Class Demolitionist : PlayerPawn { let type = (class)(AllActorClasses[i]); if ( !type ) continue; + let rep = GetReplacement(type); + // don't give replaced items + if ( rep != type ) continue; // no fabricators before hexen if ( !(gameinfo.gametype&GAME_HEXEN) && (type is 'AmmoFabricator') ) continue; // no barriers outside doom @@ -381,6 +377,7 @@ Class Demolitionist : PlayerPawn SWWMCollectible(item).propagated = true; // no score or anims if ( !item.CallTryPickup(self) ) item.Destroy(); } + if ( !giveall ) return; } if ( giveall ) return; let type = name; diff --git a/zscript/utility/swwm_utility.zsc b/zscript/utility/swwm_utility.zsc index 35e11a25f..e44a55c87 100644 --- a/zscript/utility/swwm_utility.zsc +++ b/zscript/utility/swwm_utility.zsc @@ -1664,6 +1664,18 @@ Class SWWMUtility return false; } + // used by the store + static bool IsVipItemClass( Class target ) + { + if ( (target is 'Ynykron') || (target is 'GrandLance') || (target is 'RayKhom') ) + return true; + if ( (target is 'GoldShell') || (target is 'YnykronAmmo') || (target is 'GrandAmmo') || (target is 'GrandSpear') || (target is 'UltimatePod') || (target is 'UltimateAmmo') ) + return true; + if ( (target is 'Mykradvo') || (target is 'AngerySigil') || (target is 'DivineSprite') ) + return true; + return false; + } + static bool IsScoreItem( Actor target ) { if ( target is 'Key' ) diff --git a/zscript/weapons/swwm_deathlydeathcannon.zsc b/zscript/weapons/swwm_deathlydeathcannon.zsc index e45f440fb..df3d3784f 100644 --- a/zscript/weapons/swwm_deathlydeathcannon.zsc +++ b/zscript/weapons/swwm_deathlydeathcannon.zsc @@ -241,7 +241,7 @@ Class Ynykron : SWWMWeapon Weapon.SlotNumber 0; Weapon.SelectionOrder 9000; Weapon.UpSound "ynykron/select"; - Stamina 5000000; + Stamina -5000000; Weapon.AmmoType1 "YnykronAmmo"; Weapon.AmmoGive1 1; SWWMWeapon.DropAmmoType "YnykronAmmo";