From 1cbfd4b97d569de0aa3bf513aac66d0a9a578ca6 Mon Sep 17 00:00:00 2001 From: Marisa Kirisame Date: Mon, 22 Mar 2021 01:26:15 +0100 Subject: [PATCH] Begginings of achievement system. Fix projectile detection. --- cvarinfo.txt | 18 +- graphics/Achievements/AchievementNone.png | Bin 0 -> 2062 bytes graphics/Achievements/AchievementUnknown.png | Bin 0 -> 652 bytes graphics/HUD/AchievementNotification.png | Bin 0 -> 185 bytes language.def_base | 4 - language.es_base | 4 - language.version | 4 +- zscript.txt | 1 + zscript/handler/swwm_handler_iwantdie.zsc | 2 +- zscript/handler/swwm_handler_process.zsc | 1 + zscript/handler/swwm_handler_worldthings.zsc | 2 +- .../swwm_statichandler_achievements.zsc | 566 ++++++++++++++++ zscript/hud/swwm_hudextra.zsc | 67 ++ zscript/items/swwm_funstuff.zsc | 3 +- zscript/kbase/swwm_kbase.zsc | 634 +++++++++++++++++- zscript/swwm_statichandler.zsc | 26 +- zscript/swwm_thinkers_player.zsc | 5 +- zscript/utility/swwm_utility.zsc | 63 ++ zscript/weapons/swwm_baseweapon_melee.zsc | 2 +- zscript/weapons/swwm_deepdarkimpact.zsc | 2 +- 20 files changed, 1369 insertions(+), 35 deletions(-) create mode 100644 graphics/Achievements/AchievementNone.png create mode 100644 graphics/Achievements/AchievementUnknown.png create mode 100644 graphics/HUD/AchievementNotification.png create mode 100644 zscript/handler/swwm_statichandler_achievements.zsc diff --git a/cvarinfo.txt b/cvarinfo.txt index 92a51c2dc..4eba9a4a1 100644 --- a/cvarinfo.txt +++ b/cvarinfo.txt @@ -156,7 +156,6 @@ nosave int swwm_achievement_gravity = 0; nosave int swwm_achievement_flight = 0; nosave int swwm_achievement_cliffyb = 0; nosave int swwm_achievement_par = 0; -nosave int swwm_achievement_fuck = 0; nosave int swwm_achievement_oneguy = 0; nosave int swwm_achievement_golden = 0; nosave int swwm_achievement_gib = 0; @@ -214,7 +213,6 @@ nosave int swwm_achievement_fuller = 0; nosave int swwm_achievement_pene = 0; nosave int swwm_achievement_acid = 0; nosave int swwm_achievement_salt = 0; -nosave int swwm_achievement_nobuy = 0; nosave int swwm_achievement_mega = 0; nosave int swwm_achievement_sanic = 0; nosave int swwm_achievement_tele = 0; @@ -228,13 +226,15 @@ nosave int swwm_achievement_snake = 0; nosave int swwm_achievement_smb = 0; nosave int swwm_achievement_tyrian = 0; nosave int swwm_achievement_bof = 0; -// cross-session progress cvars (everything else is part of a static thinker) +// cross-session progress cvars nosave int swwm_progress_gcsandwich = 0; nosave int swwm_progress_ghost = 0; nosave int swwm_progress_allitems = 0; +nosave int swwm_progress_conga = 0; +nosave int swwm_progress_explogun = 0; nosave int swwm_progress_gravity = 0; +nosave int swwm_progress_flight = 0; nosave int swwm_progress_par = 0; -nosave int swwm_progress_fuck = 0; nosave int swwm_progress_golden = 0; nosave int swwm_progress_gib = 0; nosave int swwm_progress_barrier = 0; @@ -244,8 +244,10 @@ nosave int swwm_progress_fuel = 0; nosave int swwm_progress_slayer = 0; nosave int swwm_progress_stomp = 0; nosave int swwm_progress_thruwall = 0; +nosave int swwm_progress_lead = 0; nosave int swwm_progress_love = 0; nosave int swwm_progress_butts = 0; +nosave int swwm_progress_plush = 0; nosave int swwm_progress_bustin = 0; nosave int swwm_progress_moth = 0; nosave int swwm_progress_iwad = 0; @@ -260,15 +262,23 @@ nosave int swwm_progress_friend = 0; nosave int swwm_progress_shock = 0; nosave int swwm_progress_balls = 0; nosave int swwm_progress_refresh = 0; +nosave int swwm_progress_step = 0; nosave int swwm_progress_sunny = 0; nosave int swwm_progress_thicc = 0; +nosave int swwm_progress_allcoll = 0; nosave int swwm_progress_slemg = 0; +nosave int swwm_progress_dosh = 0; nosave int swwm_progress_jump = 0; +nosave int swwm_progress_ezkill = 0; +nosave int swwm_progress_dakka = 0; nosave int swwm_progress_roast = 0; nosave int swwm_progress_dab = 0; +nosave int swwm_progress_hnd = 0; nosave int swwm_progress_gepgun = 0; +nosave int swwm_progress_pene = 0; nosave int swwm_progress_acid = 0; nosave int swwm_progress_mega = 0; +nosave int swwm_progress_sanic = 0; nosave int swwm_progress_bune = 0; nosave int swwm_progress_bonk = 0; nosave int swwm_progress_anom = 0; diff --git a/graphics/Achievements/AchievementNone.png b/graphics/Achievements/AchievementNone.png new file mode 100644 index 0000000000000000000000000000000000000000..8ba11da8d98a966584d46310aa428aed3bd84c02 GIT binary patch literal 2062 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4kiW$hCdQ-7c(%hU-fix4Ds;J4b3bFzAn1& zyPfB>9lkAwqR+_+$DdnrYxKJ&%;W1+2xsKR#P0* zouig3_AX!Rd0NaPI?Bdbqx1TOq=Lgi%-bf4pZuhBa@v<|b>H`?AI<&s<>jk8#pl1z zEk3{deP?b>?%C<_`8U2i{yMvUSK;fA>D%Yu+VuF#wzN8?lRsZC`@5~M{Per$ z_v-V`%YT1k%l=06MziLe2q%U^0z6zDxBYT&{`%}Yq3OZq3Jd|?Nof0K6RYHDk z&8nBP7HO?NmF(t{*6~ZB*4SeaYn1;Qj?8?i}y1ZiGKUO`Y+#heVfLR z%EEF|&9h^pr;?-8A=$SPhTY8Gjq1@>d#$k^rA1;xIa{~)q$vdCFiBXf+Fxm2y$w`*cMw}zC0i=c9(j*$FLMU6ZDlH7IMWDYK9m?7x- zJRzy8>os9z^{2hXJNf(aPwm`!_V1ZnAJfCyo-y+-T-uO$xKov-!v42plOy9q z?E;DR&?Sb!os+YBuDnY9dGFVv*Vg98PcvUi$aup){r%j$MBni2`!8cSOk&qs{;lTq z(@|Vdc)O(bV`+eck9>LH7MGoBdCKChcaOxuuR3z9e)#p|xW)t<-3>ax&!b=W+IN0vVNMGo_qP5N}@K}Lqs z`mp7XcNuxKSwHz0ryZ!(&B5T@`-j<2=VgkG(eku{5)lyrP4OimFC2WYoIg`3)iWt% z!IYhISf9N3KIi?u;HpnwH`SirG-tcq-Cg&p?HLagROBCiXCH*!W_qvM781 z6utP!0O*XJlktBwU==9M1i2`KCqUTuyvoT6scpPtn%3@1N&y!WqTNni2x)`zLxLYKGhjB8sy_piOFQ_0~=KiBv1clG#X zcb!fRyn6Ao?o|D~F@+Bb!aO~bUT6xp94WXEyFKMzX0<^jp}IEg9rAc?Rc|E#XfbdZ$jkr}}@7!A}dbId4ziFJJKH zMfbZ|tX50inC9@lKXmlpV*O`ttpzq!tNj;^{`Ar{pyMJ>$jpl&6C3_deI?}jYg(Yv`IdXX8zP^3i3hQrFzBzYU zbfHJe;Z>>8Z`ZzypBvJ@fAwB*nT*%(GU}Kmek_Tutah=!_ax71 zP8^a(%_V7x|YJdrwY(vhLZ3{d42vKV%hse0X5V_Jw<2Z@c~O-o~o4>rU#oBbLdWlDutTQR*c5^FiaK`xmc1EvyRDkKL8jdUnyWw6^EGy)O=& z`4H1B(<E~Zve!X^UyyU+GgQ`Q)_X3v5%n6U@aNNiF=i{U7FQ=oI@otNM^>5#! zcW*Op{9ln2y}*0#_lNh__xiZ0u%Fz{`ZZ*yktc)g)AQl^pwj6}gdFQOc89|IZ})u7 zO4;x@s4xCQ@Truuy!xBpvs+~l5XlK(PI zMvpb~kL4feRAqUh`{7|jlaR*Ot5eK>pZ0e=wc_@TMy-aNUw3vn#fPpts?|9~EAZ>3 zr~ekM4@tTD)asP*k$F>hgt7?i*4;hnV5cg}2V-Rs2c3EEwO4Alh=_|={@^Q#JpJSW z+xedF-K&-r6m4CT6YaP)KQP%d^zW3zdzn_O>c9GSZJV$+hr^7lkdyw4vsOr#KDO&- zdG*}VD7%euli^m&HKn_YxBqcqdR12a@s-J+mkp6Rt=sRlQDhZ&J^H3Z@N(DR4Nlywo`&5{Vy)A**9%sp4gvFB1(O%BE_Kbl z>~QJK@!1vU&w3x6{N!xy_c_(?_6i5ii>}zYD{gJ>we8!=%f5g6{=KYx+xAzpx4!!I z>eQi{$P+CKgjko%ny9tZ^sk7Qc83KrlR{2k zUfjIB_t?RMyC--2JusP>&tk{3_RS3mKfXWytv9<*=9AdJAK^x?Tz{Usn3^}iT43KC z?YUxU;_BmKa}tIZ|WtM zv-Ra09iC{ua7ps*-2LhzLva7bxK;0cUaP!pp77?t^O(P9Z~a+&QS_HXKU0;kY7&Qw zQRJM;kVhLszx1+AF%~-7Byd^X{L%lT^?5H{{LXPHK9;bVC-AU!%HC)ES!=W|A2E>Z zXY`dR?f*X^&bC^j_wvR17v{UagiO6u8pm^-<44V2j!2C?6$1Q=ZFn6M`uZ;9TR)%t z{JQ}Al?e?iby9jxuQOa0^2DNrXKT_4eY?|pzOPGXV=lfOcp`EI%j()^vX8S2c63>M zVhCj7KXNWIJ3lXEwX`9t&I7Na4}3ZmmovBCUOS(S%RBN?MPu{oxu(zd6jt1@Fl>9O zaH8?4o2Z`a4?K@O$bNA87dz)s&JV`~?uUVr NnWw9t%Q~loCIGfcG*tiq literal 0 HcmV?d00001 diff --git a/graphics/HUD/AchievementNotification.png b/graphics/HUD/AchievementNotification.png new file mode 100644 index 0000000000000000000000000000000000000000..834956e544e6deee6cd5ad9560e1fb4b40c1c37a GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0y~yV0g*Ez@W;)%)r19YJ6Fqfq_9Hz$e6&0R}jD1Oy}$ z6bu|366zEB_e<(8;bmZ8U@8gn3uZX;#L;;%0|SGfr;B4qMC;qLhP(_4JPZff*i|?( zHZTbp9AFT-aQ>pYXA_0A<+L=**lUD=nH_0HvbNYLN;aeAe- U0uDEJKL$C$)78&qol`;+0AC+81poj5 literal 0 HcmV?d00001 diff --git a/language.def_base b/language.def_base index a49472a54..a69817ae0 100644 --- a/language.def_base +++ b/language.def_base @@ -854,8 +854,6 @@ SWWM_ACHIEVEMENT_CLIFFYB_TAG = "Errand Boy Bullshit"; SWWM_ACHIEVEMENT_CLIFFYB_TXT = "Finish a map without collecting any keys"; SWWM_ACHIEVEMENT_PAR_TAG = "Fast"; SWWM_ACHIEVEMENT_PAR_TXT = "Beat the par time in %d maps"; -SWWM_ACHIEVEMENT_FUCK_TAG = "Firestarter"; -SWWM_ACHIEVEMENT_FUCK_TXT = "Kill %d enemies with FYS shells"; SWWM_ACHIEVEMENT_ONEGUY_TAG = "Fuck this Guy in Particular"; SWWM_ACHIEVEMENT_ONEGUY_TXT = "Use the Ynykron Artifact to kill a single non-boss enemy"; SWWM_ACHIEVEMENT_GOLDEN_TAG = "Golden Shower"; @@ -970,8 +968,6 @@ SWWM_ACHIEVEMENT_ACID_TAG = "Fizzy Goodness"; SWWM_ACHIEVEMENT_ACID_TXT = "Melt %d enemies with Telebrium Flechettes"; SWWM_ACHIEVEMENT_SALT_TAG = "Maximum Oversalt"; SWWM_ACHIEVEMENT_SALT_TXT = "Shoot 25 Saltshot rounds simultaneously"; -SWWM_ACHIEVEMENT_NOBUY_TAG = "Sustained Savings"; -SWWM_ACHIEVEMENT_NOBUY_TXT = "Don't spend any money for %d maps straight"; SWWM_ACHIEVEMENT_MEGA_TAG = "Megadeath"; SWWM_ACHIEVEMENT_MEGA_TXT = "Kill a grand total of one million enemies"; SWWM_ACHIEVEMENT_SANIC_TAG = "CHILLI DOGS"; diff --git a/language.es_base b/language.es_base index bce8918e5..cd456f0e3 100644 --- a/language.es_base +++ b/language.es_base @@ -756,8 +756,6 @@ SWWM_ACHIEVEMENT_CLIFFYB_TAG = "Mierdas de Recadero"; SWWM_ACHIEVEMENT_CLIFFYB_TXT = "Termina un mapa sin obtener ninguna llave"; SWWM_ACHIEVEMENT_PAR_TAG = "Rápido"; SWWM_ACHIEVEMENT_PAR_TXT = "Supera el tiempo par en %d mapas"; -SWWM_ACHIEVEMENT_FUCK_TAG = "Incendiario"; -SWWM_ACHIEVEMENT_FUCK_TXT = "Mata %d enemigos con cartuchos FYS"; SWWM_ACHIEVEMENT_ONEGUY_TAG = "A la Mierda este Tío en Particular"; SWWM_ACHIEVEMENT_ONEGUY_TXT = "Usa el Artefacto Ynykron para matar a un único enemigo no-jefe"; SWWM_ACHIEVEMENT_GOLDEN_TAG = "Lluvia Dorada"; @@ -865,8 +863,6 @@ SWWM_ACHIEVEMENT_ACID_TAG = "La Buena Efervescencia"; SWWM_ACHIEVEMENT_ACID_TXT = "Derrite %d enemigos con Flechettes de Telebrium"; SWWM_ACHIEVEMENT_SALT_TAG = "Sobresalado Máximo"; SWWM_ACHIEVEMENT_SALT_TXT = "Dispara 25 cartuchos de sal al mismo tiempo"; -SWWM_ACHIEVEMENT_NOBUY_TAG = "Ahorro Máximo"; -SWWM_ACHIEVEMENT_NOBUY_TXT = "No gastes dinero durante %d mapas seguidos"; SWWM_ACHIEVEMENT_MEGA_TAG = "Megamuerte"; SWWM_ACHIEVEMENT_MEGA_TXT = "Mata un gran total de un millón de enemigos"; SWWM_ACHIEVEMENT_SANIC_TAG = "PERRITOS DE CHILE"; diff --git a/language.version b/language.version index 4a0994b1a..3892b971c 100644 --- a/language.version +++ b/language.version @@ -1,3 +1,3 @@ [default] -SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r394 \cu(Sun 21 Mar 16:22:55 CET 2021)\c-"; -SWWM_SHORTVER="\cw0.9.11b-pre r394 \cu(2021-03-21 16:22:55)\c-"; +SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r394 \cu(Mon 22 Mar 01:26:15 CET 2021)\c-"; +SWWM_SHORTVER="\cw0.9.11b-pre r394 \cu(2021-03-22 01:26:15)\c-"; diff --git a/zscript.txt b/zscript.txt index 309634cef..8c52399c7 100644 --- a/zscript.txt +++ b/zscript.txt @@ -45,6 +45,7 @@ version "4.5" #include "zscript/handler/swwm_handler_worldload.zsc" #include "zscript/handler/swwm_handler_worldthings.zsc" #include "zscript/handler/swwm_handler_worldtick.zsc" +#include "zscript/handler/swwm_statichandler_achievements.zsc" // menu code #include "zscript/menu/swwm_menus.zsc" #include "zscript/menu/swwm_title.zsc" diff --git a/zscript/handler/swwm_handler_iwantdie.zsc b/zscript/handler/swwm_handler_iwantdie.zsc index 8a628a475..e7d0f818e 100644 --- a/zscript/handler/swwm_handler_iwantdie.zsc +++ b/zscript/handler/swwm_handler_iwantdie.zsc @@ -21,7 +21,7 @@ extend Class SWWMHandler if ( iwantdie == -1 ) iwantdie = (G_SkillName() == StringTable.Localize("$SWWM_SKLUNATIC")); if ( iwantdie ) { - if ( e.Thing.bMISSILE && !e.Thing.FindInventory("DontDuplicate") && !e.Thing.IsZeroDamage() && (e.Thing.target && e.Thing.target.bISMONSTER && !e.Thing.target.player) ) + if ( SWWMUtility.ValidProjectile(e.Thing) && !e.Thing.FindInventory("DontDuplicate") && (e.Thing.target && e.Thing.target.bISMONSTER && !e.Thing.target.player) ) { e.Thing.speed *= 2; e.Thing.vel *= 2; diff --git a/zscript/handler/swwm_handler_process.zsc b/zscript/handler/swwm_handler_process.zsc index f32e06b1f..b866cab0e 100644 --- a/zscript/handler/swwm_handler_process.zsc +++ b/zscript/handler/swwm_handler_process.zsc @@ -237,6 +237,7 @@ extend Class SWWMHandler Console.Printf("Spread: %d",Random2[Spread]()); Console.Printf("Spreadgun: %d",Random2[Spreadgun]()); Console.Printf("TUID: %d",Random2[TUID]()); + Console.Printf("UIStuff %d",Random2[UIStuff]()); Console.Printf("Wallbuster: %d",Random2[Wallbuster]()); Console.Printf("WallbusterMenu: %d",Random2[WallbusterMenu]()); Console.Printf("Ynykron: %d",Random2[Ynykron]()); diff --git a/zscript/handler/swwm_handler_worldthings.zsc b/zscript/handler/swwm_handler_worldthings.zsc index 912e67acb..adab08e58 100644 --- a/zscript/handler/swwm_handler_worldthings.zsc +++ b/zscript/handler/swwm_handler_worldthings.zsc @@ -343,7 +343,7 @@ extend Class SWWMHandler SWWMShadow.Track(e.Thing); } // Ynykron vortex optimization (faster than a thinker iterator) - if ( e.Thing.bSHOOTABLE || (e.Thing.bMISSILE && !e.Thing.IsZeroDamage()) || (e.Thing is 'Inventory') ) + if ( e.Thing.bSHOOTABLE || SWWMUtility.ValidProjectile(e.Thing) || (e.Thing is 'Inventory') ) SuckableActors.Push(e.Thing); // vanilla blood color changes if ( (e.Thing.GetClass() == "BaronOfHell") || (e.Thing.GetClass() == "HellKnight") || (e.Thing.GetClass() == "Bishop") || (e.Thing.GetClass() == "Korax") ) diff --git a/zscript/handler/swwm_statichandler_achievements.zsc b/zscript/handler/swwm_statichandler_achievements.zsc new file mode 100644 index 000000000..c475af755 --- /dev/null +++ b/zscript/handler/swwm_statichandler_achievements.zsc @@ -0,0 +1,566 @@ +// achievement tracking + +// constants for finetuning them numbers +const SA_GCSANDWICH = 40; +const SA_GHOST = 30; +const SA_ALLITEMS = 75; +const SA_CONGA = 25; +const SA_EXPLOGUN = 5; +const SA_GRAVITY = 20; +const SA_FLIGHT = 1000; +const SA_PAR = 25; +const SA_GOLDEN = 24; +const SA_GIB = 500; +const SA_BARRIER = 30; +const SA_BOSSDASH = 20; +const SA_SNEEZE = 50; +const SA_FUEL = 200; +const SA_SLAYER = 40; +const SA_STOMP = 50; +const SA_THRUWALL = 30; +const SA_LEAD = 1500; +const SA_LOVE = 50; +const SA_BUTTS = 100; +const SA_PLUSH = 20; +const SA_BUSTIN = 40; +const SA_MOTH = 60; +const SA_BRAKE = 30; +const SA_RAGE = 40; +const SA_PARRY = 100; +const SA_ALLKILLS = 100; +const SA_ALLSECRETS = 50; +const SA_REFLECT = 50; +const SA_WAVE = 20; +const SA_FRIEND = 60; +const SA_SHOCK = 50; +const SA_BALLS = 30; +const SA_REFRESH = 40; +const SA_STEP = 60; +const SA_SUNNY = 30; +const SA_THICC = 80; +const SA_SLEMG = 100; +const SA_JUMP = 100; +const SA_EZKILL = 200; +const SA_ROAST = 30; +const SA_DAB = 60; +const SA_HND = 6; +const SA_GEPGUN = 50; +const SA_PENE = 20; +const SA_ACID = 200; +const SA_SANIC = 800; +const SA_BUNE = 150; +const SA_BONK = 300; +const SA_ANOM = 40; + +// achievement unlock tracking +extend Class SWWMStaticHandler +{ + ui int lastachievementnotify; // prevent overlap + + private ui bool CheckAchievement( Name ac, String acname, int acnum, Name acprog ) + { + let ev = CVar.FindCVar(ac); + int val = ev.GetInt(); + // manually check progress + if ( acprog != 'None' ) + { + int prog = CVar.FindCVar(acprog).GetInt(); + int maxval = acnum; + // special cases + if ( ac == 'swwm_achievement_allcoll' ) + { + int nc = 0; + for ( int i=0; i)(AllActorClasses[i]); + if ( !c || (c == 'SWWMCollectible') ) continue; + nc++; + } + maxval = nc; + } + else if ( ac == 'swwm_achievement_dakka' ) maxval = 60; + else if ( ac == 'swwm_achievement_dosh' ) maxval = 1000000000; + else if ( ac == 'swwm_achievement_mega' ) maxval = 1000000; + if ( val && (prog < maxval) ) + { + ev.SetInt(0); + val = 0; + } + else if ( !val && (prog >= maxval) ) + { + ev.SetInt(1); + val = 1; + } + } + if ( (val == 1) && (gametic > lastachievementnotify) ) + { + ev.SetInt(2); + EventHandler.SendNetworkEvent("swwmachievement."..acname.."_TAG",consoleplayer); + let notif = new("SWWMAchievementNotification").Init(acname,acnum); + StatusBar.AttachMessage(notif,-3478); + lastachievementnotify = gametic+200; + } + return (val > 0); + } + + private ui void CheckAllAchievements() + { + // don't check constantly + if ( (maptime < 105) || (maptime%35) ) return; + // cvar assigned + static const Name vars[] = + { + 'swwm_achievement_gcsandwich', + 'swwm_achievement_hdoom', + 'swwm_achievement_onestanding', + 'swwm_achievement_oopsie', + 'swwm_achievement_ghost', + 'swwm_achievement_clonk', + 'swwm_achievement_allitems', + 'swwm_achievement_conga', + 'swwm_achievement_explogun', + 'swwm_achievement_gravity', + 'swwm_achievement_flight', + 'swwm_achievement_cliffyb', + 'swwm_achievement_par', + 'swwm_achievement_oneguy', + 'swwm_achievement_golden', + 'swwm_achievement_gib', + 'swwm_achievement_barrier', + 'swwm_achievement_bossdash', + 'swwm_achievement_sneeze', + 'swwm_achievement_fuel', + 'swwm_achievement_slayer', + 'swwm_achievement_broccolidoccoli', + 'swwm_achievement_dime', + 'swwm_achievement_stomp', + 'swwm_achievement_cheat', + 'swwm_achievement_god', + 'swwm_achievement_thruwall', + 'swwm_achievement_mashiro', + 'swwm_achievement_lead', + 'swwm_achievement_love', + 'swwm_achievement_butts', + 'swwm_achievement_plush', + 'swwm_achievement_bustin', + 'swwm_achievement_moth', + 'swwm_achievement_iwad', + 'swwm_achievement_brake', + 'swwm_achievement_rage', + 'swwm_achievement_abort', + 'swwm_achievement_parry', + 'swwm_achievement_allkills', + 'swwm_achievement_allsecrets', + 'swwm_achievement_reflect', + 'swwm_achievement_sekiro', + 'swwm_achievement_wave', + 'swwm_achievement_friend', + 'swwm_achievement_shock', + 'swwm_achievement_balls', + 'swwm_achievement_refresh', + 'swwm_achievement_step', + 'swwm_achievement_sunny', + 'swwm_achievement_thicc', + 'swwm_achievement_allcoll', + 'swwm_achievement_slemg', + 'swwm_achievement_dosh', + 'swwm_achievement_jump', + 'swwm_achievement_ezkill', + 'swwm_achievement_ligma', + 'swwm_achievement_yeet', + 'swwm_achievement_mbf', + 'swwm_achievement_lightning', + 'swwm_achievement_dakka', + 'swwm_achievement_roast', + 'swwm_achievement_dab', + 'swwm_achievement_hnd', + 'swwm_achievement_gepgun', + 'swwm_achievement_fuller', + 'swwm_achievement_pene', + 'swwm_achievement_acid', + 'swwm_achievement_salt', + 'swwm_achievement_mega', + 'swwm_achievement_sanic', + 'swwm_achievement_tele', + 'swwm_achievement_bune', + 'swwm_achievement_bonk', + 'swwm_achievement_anom', + 'swwm_achievement_anone', + 'swwm_achievement_tetris', + 'swwm_achievement_pong', + 'swwm_achievement_snake', + 'swwm_achievement_smb', + 'swwm_achievement_tyrian', + 'swwm_achievement_bof' + }; + // localized name + static const String names[] = + { + "$SWWM_ACHIEVEMENT_GCSANDWICH", + "$SWWM_ACHIEVEMENT_HDOOM", + "$SWWM_ACHIEVEMENT_ONESTANDING", + "$SWWM_ACHIEVEMENT_OOPSIE", + "$SWWM_ACHIEVEMENT_GHOST", + "$SWWM_ACHIEVEMENT_CLONK", + "$SWWM_ACHIEVEMENT_ALLITEMS", + "$SWWM_ACHIEVEMENT_CONGA", + "$SWWM_ACHIEVEMENT_EXPLOGUN", + "$SWWM_ACHIEVEMENT_GRAVITY", + "$SWWM_ACHIEVEMENT_FLIGHT", + "$SWWM_ACHIEVEMENT_CLIFFYB", + "$SWWM_ACHIEVEMENT_PAR", + "$SWWM_ACHIEVEMENT_ONEGUY", + "$SWWM_ACHIEVEMENT_GOLDEN", + "$SWWM_ACHIEVEMENT_GIB", + "$SWWM_ACHIEVEMENT_BARRIER", + "$SWWM_ACHIEVEMENT_BOSSDASH", + "$SWWM_ACHIEVEMENT_SNEEZE", + "$SWWM_ACHIEVEMENT_FUEL", + "$SWWM_ACHIEVEMENT_SLAYER", + "$SWWM_ACHIEVEMENT_BROCCOLIDOCCOLI", + "$SWWM_ACHIEVEMENT_DIME", + "$SWWM_ACHIEVEMENT_STOMP", + "$SWWM_ACHIEVEMENT_CHEAT", + "$SWWM_ACHIEVEMENT_GOD", + "$SWWM_ACHIEVEMENT_THRUWALL", + "$SWWM_ACHIEVEMENT_MASHIRO", + "$SWWM_ACHIEVEMENT_LEAD", + "$SWWM_ACHIEVEMENT_LOVE", + "$SWWM_ACHIEVEMENT_BUTTS", + "$SWWM_ACHIEVEMENT_PLUSH", + "$SWWM_ACHIEVEMENT_BUSTIN", + "$SWWM_ACHIEVEMENT_MOTH", + "$SWWM_ACHIEVEMENT_IWAD", + "$SWWM_ACHIEVEMENT_BRAKE", + "$SWWM_ACHIEVEMENT_RAGE", + "$SWWM_ACHIEVEMENT_ABORT", + "$SWWM_ACHIEVEMENT_PARRY", + "$SWWM_ACHIEVEMENT_ALLKILLS", + "$SWWM_ACHIEVEMENT_ALLSECRETS", + "$SWWM_ACHIEVEMENT_REFLECT", + "$SWWM_ACHIEVEMENT_SEKIRO", + "$SWWM_ACHIEVEMENT_WAVE", + "$SWWM_ACHIEVEMENT_FRIEND", + "$SWWM_ACHIEVEMENT_SHOCK", + "$SWWM_ACHIEVEMENT_BALLS", + "$SWWM_ACHIEVEMENT_REFRESH", + "$SWWM_ACHIEVEMENT_STEP", + "$SWWM_ACHIEVEMENT_SUNNY", + "$SWWM_ACHIEVEMENT_THICC", + "$SWWM_ACHIEVEMENT_ALLCOLL", + "$SWWM_ACHIEVEMENT_SLEMG", + "$SWWM_ACHIEVEMENT_DOSH", + "$SWWM_ACHIEVEMENT_JUMP", + "$SWWM_ACHIEVEMENT_EZKILL", + "$SWWM_ACHIEVEMENT_LIGMA", + "$SWWM_ACHIEVEMENT_YEET", + "$SWWM_ACHIEVEMENT_MBF", + "$SWWM_ACHIEVEMENT_LIGHTNING", + "$SWWM_ACHIEVEMENT_DAKKA", + "$SWWM_ACHIEVEMENT_ROAST", + "$SWWM_ACHIEVEMENT_DAB", + "$SWWM_ACHIEVEMENT_HND", + "$SWWM_ACHIEVEMENT_GEPGUN", + "$SWWM_ACHIEVEMENT_FULLER", + "$SWWM_ACHIEVEMENT_PENE", + "$SWWM_ACHIEVEMENT_ACID", + "$SWWM_ACHIEVEMENT_SALT", + "$SWWM_ACHIEVEMENT_MEGA", + "$SWWM_ACHIEVEMENT_SANIC", + "$SWWM_ACHIEVEMENT_TELE", + "$SWWM_ACHIEVEMENT_BUNE", + "$SWWM_ACHIEVEMENT_BONK", + "$SWWM_ACHIEVEMENT_ANOM", + "$SWWM_ACHIEVEMENT_ANONE", + "$SWWM_ACHIEVEMENT_TETRIS", + "$SWWM_ACHIEVEMENT_PONG", + "$SWWM_ACHIEVEMENT_SNAKE", + "$SWWM_ACHIEVEMENT_SMB", + "$SWWM_ACHIEVEMENT_TYRIAN", + "$SWWM_ACHIEVEMENT_BOF" + }; + // has number in txt + static const int number[] = + { + SA_GCSANDWICH, + 0, // HDOOM + 0, // ONESTANDING + 0, // OOPSIE + SA_GHOST, + 0, // CLONK + SA_ALLITEMS, + SA_CONGA, + SA_EXPLOGUN, + SA_GRAVITY, + SA_FLIGHT, + 0, // CLIFFYB + SA_PAR, + 0, // ONEGUY + SA_GOLDEN, + SA_GIB, + SA_BARRIER, + SA_BOSSDASH, + SA_SNEEZE, + SA_FUEL, + SA_SLAYER, + 0, // BROCCOLIDOCCOLI + 0, // DIME + SA_STOMP, + 0, // CHEAT + 0, // GOD + SA_THRUWALL, + 0, // MASHIRO + SA_LEAD, + SA_LOVE, + SA_BUTTS, + SA_PLUSH, + SA_BUSTIN, + SA_MOTH, + 0, // IWAD + SA_BRAKE, + SA_RAGE, + 0, // ABORT + SA_PARRY, + SA_ALLKILLS, + SA_ALLSECRETS, + SA_REFLECT, + 0, // SEKIRO + SA_WAVE, + SA_FRIEND, + SA_SHOCK, + SA_BALLS, + SA_REFRESH, + SA_STEP, + SA_SUNNY, + SA_THICC, + 0, // ALLCOLL + SA_SLEMG, + 0, // DOSH + SA_JUMP, + SA_EZKILL, + 0, // LIGMA + 0, // YEET + 0, // MBF + 0, // LIGHTNING + 0, // DAKKA + SA_ROAST, + SA_DAB, + SA_HND, + SA_GEPGUN, + 0, // FULLER + SA_PENE, + SA_ACID, + 0, // SALT + 0, // MEGA + SA_SANIC, + 0, // TELE + SA_BUNE, + SA_BONK, + SA_ANOM, + 0, // ANONE + 0, // TETRIS + 0, // PONG + 0, // SNAKE + 0, // SMB + 0, // TYRIAN + 0 // BOF + }; + // is ignored (hide away achievements that can't be done yet) + static const bool ignoreme[] = + { + false, // GCSANDWICH + false, // HDOOM + false, // ONESTANDING + false, // OOPSIE + false, // GHOST + false, // CLONK + false, // ALLITEMS + false, // CONGA + false, // EXPLOGUN + false, // GRAVITY + false, // FLIGHT + false, // CLIFFYB + false, // PAR + false, // ONEGUY + false, // GOLDEN + false, // GIB + false, // BARRIER + false, // BOSSDASH + false, // SNEEZE + false, // FUEL + false, // SLAYER + false, // BROCCOLIDOCCOLI + false, // DIME + false, // STOMP + false, // CHEAT + false, // GOD + false, // THRUWALL + true, // MASHIRO + false, // LEAD + false, // LOVE + false, // BUTTS + false, // PLUSH + false, // BUSTIN + false, // MOTH + false, // IWAD + false, // BRAKE + false, // RAGE + false, // ABORT + false, // PARRY + false, // ALLKILLS + false, // ALLSECRETS + false, // REFLECT + false, // SEKIRO + false, // WAVE + false, // FRIEND + false, // SHOCK + false, // BALLS + false, // REFRESH + false, // STEP + false, // SUNNY + false, // THICC + false, // ALLCOLL + false, // SLEMG + false, // DOSH + false, // JUMP + false, // EZKILL + false, // LIGMA + false, // YEET + false, // MBF + true, // LIGHTNING + true, // DAKKA + true, // ROAST + true, // DAB + true, // HND + true, // GEPGUN + true, // FULLER + true, // PENE + false, // ACID + false, // SALT + false, // MEGA + false, // SANIC + false, // TELE + false, // BUNE + false, // BONK + false, // ANOM + false, // ANONE + true, // TETRIS + true, // PONG + true, // SNAKE + true, // SMB + true, // TYRIAN + true // BOF + }; + // progress tracking cvar (if any) + static const Name pvar[] = + { + 'swwm_progress_gcsandwich', // GCSANDWICH + 'None', // HDOOM + 'None', // ONESTANDING + 'None', // OOPSIE + 'swwm_progress_ghost', // GHOST + 'None', // CLONK + 'swwm_progress_allitems', // ALLITEMS + 'swwm_progress_conga', // CONGA + 'swwm_progress_explogun', // EXPLOGUN + 'swwm_progress_gravity', // GRAVITY + 'swwm_progress_flight', // FLIGHT + 'None', // CLIFFYB + 'swwm_progress_par', // PAR + 'None', // ONEGUY + 'swwm_progress_golden', // GOLDEN + 'swwm_progress_gib', // GIB + 'swwm_progress_barrier', // BARRIER + 'swwm_progress_bossdash', // BOSSDASH + 'swwm_progress_sneeze', // SNEEZE + 'swwm_progress_fuel', // FUEL + 'swwm_progress_slayer', // SLAYER + 'None', // BROCCOLIDOCCOLI + 'None', // DIME + 'swwm_progress_stomp', // STOMP + 'None', // CHEAT + 'None', // GOD + 'swwm_progress_thruwall', // THRUWALL + 'None', // MASHIRO + 'swwm_progress_lead', // LEAD + 'swwm_progress_love', // LOVE + 'swwm_progress_butts', // BUTTS + 'swwm_progress_plush', // PLUSH + 'swwm_progress_bustin', // BUSTIN + 'swwm_progress_moth', // MOTH + 'None', // IWAD + 'swwm_progress_brake', // BRAKE + 'swwm_progress_rage', // RAGE + 'None', // ABORT + 'swwm_progress_parry', // PARRY + 'swwm_progress_allkills', // ALLKILLS + 'swwm_progress_allsecrets', // ALLSECRETS + 'swwm_progress_reflect', // REFLECT + 'None', // SEKIRO + 'swwm_progress_wave', // WAVE + 'swwm_progress_friend', // FRIEND + 'swwm_progress_shock', // SHOCK + 'swwm_progress_balls', // BALLS + 'swwm_progress_refresh', // REFRESH + 'swwm_progress_step', // STEP + 'swwm_progress_sunny', // SUNNY + 'swwm_progress_thicc', // THICC + 'swwm_progress_allcoll', // ALLCOLL + 'swwm_progress_slemg', // SLEMG + 'swwm_progress_dosh', // DOSH + 'swwm_progress_jump', // JUMP + 'swwm_progress_ezkill', // EZKILL + 'None', // LIGMA + 'None', // YEET + 'None', // MBF + 'None', // LIGHTNING + 'swwm_progress_dakka', // DAKKA + 'swwm_progress_roast', // ROAST + 'swwm_progress_dab', // DAB + 'swwm_progress_hnd', // HND + 'swwm_progress_gepgun', // GEPGUN + 'None', // FULLER + 'swwm_progress_pene', // PENE + 'swwm_progress_acid', // ACID + 'None', // SALT + 'swwm_progress_mega', // MEGA + 'swwm_progress_sanic', // SANIC + 'None', // TELE + 'swwm_progress_bune', // BUNE + 'swwm_progress_bonk', // BONK + 'swwm_progress_anom', // ANOM + 'None', // ANONE + 'None', // TETRIS + 'None', // PONG + 'None', // SNAKE + 'None', // SMB + 'None', // TYRIAN + 'None' // BOF + }; + bool alldone = true; + for ( int i=0; i lastachievementnotify) ) + { + ev.SetInt(2); + EventHandler.SendNetworkEvent("swwmachievement.$SWWM_ACHIEVEMENT_EVERYTHING_TAG",consoleplayer); + let notif = new("SWWMAchievementNotification").Init("$SWWM_ACHIEVEMENT_EVERYTHING"); + StatusBar.AttachMessage(notif,-3478); + lastachievementnotify = gametic+200; + } + } +} diff --git a/zscript/hud/swwm_hudextra.zsc b/zscript/hud/swwm_hudextra.zsc index bcfabfc62..c0a24176d 100644 --- a/zscript/hud/swwm_hudextra.zsc +++ b/zscript/hud/swwm_hudextra.zsc @@ -156,3 +156,70 @@ Class QueuedFlash int tic; Actor cam; } + +// Achievement notification +Class SWWMAchievementNotification : HUDMessageBase +{ + String tag, txt; + int num; + TextureID icon, frame; + double tics, holdtics, fadeintics, fadeouttics; + transient Font tewifont, mplusfont, miniwifont, k6x8font; + + SWWMAchievementNotification Init( String bname, int bnum = 0 ) + { + tag = bname.."_TAG"; + txt = bname.."_TXT"; + num = bnum; + icon = TexMan.CheckForTexture(StringTable.Localize(bname.."_PIC"),TexMan.Type_Any); + // fallback icon + if ( !icon.IsValid() ) icon = TexMan.CheckForTexture("graphics/Achievements/AchievementNone.png",TexMan.Type_Any); + frame = TexMan.CheckForTexture("graphics/HUD/AchievementNotification.png",TexMan.Type_Any); + holdtics = 150; + fadeintics = 20; + fadeouttics = 30; + tics = 0; + return self; + } + + override bool Tick() + { + return (++tics > holdtics+fadeintics+fadeouttics); + } + + override void Draw( int bottom, int visibility ) + { + if ( !tewifont ) tewifont = Font.GetFont('TewiShaded'); + if ( !mplusfont ) mplusfont = Font.GetFont('MPlusShaded'); + if ( !miniwifont ) miniwifont = Font.GetFont('MiniwiShaded'); + if ( !k6x8font ) k6x8font = Font.GetFont('k6x8Shaded'); + let fnt = tewifont; + let fnt2 = miniwifont; + if ( language ~== "jp" ) + { + fnt = mplusfont; + fnt2 = k6x8font; + } + double margin = swwm_hudmargin; + Vector2 hs; + if ( swwm_hudscale <= 0 ) hs = StatusBar.GetHUDScale(); + else hs.x = swwm_hudscale; + Vector2 ss = (Screen.GetWidth()/hs.x,Screen.GetHeight()/hs.y); + double alpha = (tics tabs; int curtab, oldtab; @@ -57,6 +65,7 @@ Class DemolitionistMenu : GenericMenu Array sorted_mstats; // sorted by killcount Array filtered_lstats; // filtered if necessary + entry for current map LevelStat curlstat; + Array achievements; // array created once, then sorted as needed // inventory lists Array invlist; // lore stuff @@ -333,6 +342,478 @@ Class DemolitionistMenu : GenericMenu } if ( tabs[curtab] == TAB_LIBRARY ) sel1 = swwm_lastloretab; else if ( tabs[curtab] == TAB_STATS ) sel1 = swwm_laststattab; + // load achievements + LoadAchievements(); + } + + // this is very spaghetti, sorry + private void LoadAchievements() + { + // cvar assigned + static const Name vars[] = + { + 'swwm_achievement_gcsandwich', + 'swwm_achievement_hdoom', + 'swwm_achievement_onestanding', + 'swwm_achievement_oopsie', + 'swwm_achievement_ghost', + 'swwm_achievement_clonk', + 'swwm_achievement_allitems', + 'swwm_achievement_conga', + 'swwm_achievement_explogun', + 'swwm_achievement_gravity', + 'swwm_achievement_flight', + 'swwm_achievement_cliffyb', + 'swwm_achievement_par', + 'swwm_achievement_oneguy', + 'swwm_achievement_golden', + 'swwm_achievement_gib', + 'swwm_achievement_barrier', + 'swwm_achievement_bossdash', + 'swwm_achievement_sneeze', + 'swwm_achievement_fuel', + 'swwm_achievement_slayer', + 'swwm_achievement_broccolidoccoli', + 'swwm_achievement_dime', + 'swwm_achievement_stomp', + 'swwm_achievement_cheat', + 'swwm_achievement_god', + 'swwm_achievement_thruwall', + 'swwm_achievement_mashiro', + 'swwm_achievement_lead', + 'swwm_achievement_love', + 'swwm_achievement_butts', + 'swwm_achievement_plush', + 'swwm_achievement_bustin', + 'swwm_achievement_moth', + 'swwm_achievement_iwad', + 'swwm_achievement_brake', + 'swwm_achievement_rage', + 'swwm_achievement_abort', + 'swwm_achievement_parry', + 'swwm_achievement_allkills', + 'swwm_achievement_allsecrets', + 'swwm_achievement_reflect', + 'swwm_achievement_sekiro', + 'swwm_achievement_wave', + 'swwm_achievement_friend', + 'swwm_achievement_shock', + 'swwm_achievement_balls', + 'swwm_achievement_refresh', + 'swwm_achievement_step', + 'swwm_achievement_sunny', + 'swwm_achievement_thicc', + 'swwm_achievement_everything', + 'swwm_achievement_allcoll', + 'swwm_achievement_slemg', + 'swwm_achievement_dosh', + 'swwm_achievement_jump', + 'swwm_achievement_ezkill', + 'swwm_achievement_ligma', + 'swwm_achievement_yeet', + 'swwm_achievement_mbf', + 'swwm_achievement_lightning', + 'swwm_achievement_dakka', + 'swwm_achievement_roast', + 'swwm_achievement_dab', + 'swwm_achievement_hnd', + 'swwm_achievement_gepgun', + 'swwm_achievement_fuller', + 'swwm_achievement_pene', + 'swwm_achievement_acid', + 'swwm_achievement_salt', + 'swwm_achievement_mega', + 'swwm_achievement_sanic', + 'swwm_achievement_tele', + 'swwm_achievement_bune', + 'swwm_achievement_bonk', + 'swwm_achievement_anom', + 'swwm_achievement_anone', + 'swwm_achievement_tetris', + 'swwm_achievement_pong', + 'swwm_achievement_snake', + 'swwm_achievement_smb', + 'swwm_achievement_tyrian', + 'swwm_achievement_bof' + }; + // localized name + static const String names[] = + { + "$SWWM_ACHIEVEMENT_GCSANDWICH", + "$SWWM_ACHIEVEMENT_HDOOM", + "$SWWM_ACHIEVEMENT_ONESTANDING", + "$SWWM_ACHIEVEMENT_OOPSIE", + "$SWWM_ACHIEVEMENT_GHOST", + "$SWWM_ACHIEVEMENT_CLONK", + "$SWWM_ACHIEVEMENT_ALLITEMS", + "$SWWM_ACHIEVEMENT_CONGA", + "$SWWM_ACHIEVEMENT_EXPLOGUN", + "$SWWM_ACHIEVEMENT_GRAVITY", + "$SWWM_ACHIEVEMENT_FLIGHT", + "$SWWM_ACHIEVEMENT_CLIFFYB", + "$SWWM_ACHIEVEMENT_PAR", + "$SWWM_ACHIEVEMENT_ONEGUY", + "$SWWM_ACHIEVEMENT_GOLDEN", + "$SWWM_ACHIEVEMENT_GIB", + "$SWWM_ACHIEVEMENT_BARRIER", + "$SWWM_ACHIEVEMENT_BOSSDASH", + "$SWWM_ACHIEVEMENT_SNEEZE", + "$SWWM_ACHIEVEMENT_FUEL", + "$SWWM_ACHIEVEMENT_SLAYER", + "$SWWM_ACHIEVEMENT_BROCCOLIDOCCOLI", + "$SWWM_ACHIEVEMENT_DIME", + "$SWWM_ACHIEVEMENT_STOMP", + "$SWWM_ACHIEVEMENT_CHEAT", + "$SWWM_ACHIEVEMENT_GOD", + "$SWWM_ACHIEVEMENT_THRUWALL", + "$SWWM_ACHIEVEMENT_MASHIRO", + "$SWWM_ACHIEVEMENT_LEAD", + "$SWWM_ACHIEVEMENT_LOVE", + "$SWWM_ACHIEVEMENT_BUTTS", + "$SWWM_ACHIEVEMENT_PLUSH", + "$SWWM_ACHIEVEMENT_BUSTIN", + "$SWWM_ACHIEVEMENT_MOTH", + "$SWWM_ACHIEVEMENT_IWAD", + "$SWWM_ACHIEVEMENT_BRAKE", + "$SWWM_ACHIEVEMENT_RAGE", + "$SWWM_ACHIEVEMENT_ABORT", + "$SWWM_ACHIEVEMENT_PARRY", + "$SWWM_ACHIEVEMENT_ALLKILLS", + "$SWWM_ACHIEVEMENT_ALLSECRETS", + "$SWWM_ACHIEVEMENT_REFLECT", + "$SWWM_ACHIEVEMENT_SEKIRO", + "$SWWM_ACHIEVEMENT_WAVE", + "$SWWM_ACHIEVEMENT_FRIEND", + "$SWWM_ACHIEVEMENT_SHOCK", + "$SWWM_ACHIEVEMENT_BALLS", + "$SWWM_ACHIEVEMENT_REFRESH", + "$SWWM_ACHIEVEMENT_STEP", + "$SWWM_ACHIEVEMENT_SUNNY", + "$SWWM_ACHIEVEMENT_THICC", + "$SWWM_ACHIEVEMENT_EVERYTHING", + "$SWWM_ACHIEVEMENT_ALLCOLL", + "$SWWM_ACHIEVEMENT_SLEMG", + "$SWWM_ACHIEVEMENT_DOSH", + "$SWWM_ACHIEVEMENT_JUMP", + "$SWWM_ACHIEVEMENT_EZKILL", + "$SWWM_ACHIEVEMENT_LIGMA", + "$SWWM_ACHIEVEMENT_YEET", + "$SWWM_ACHIEVEMENT_MBF", + "$SWWM_ACHIEVEMENT_LIGHTNING", + "$SWWM_ACHIEVEMENT_DAKKA", + "$SWWM_ACHIEVEMENT_ROAST", + "$SWWM_ACHIEVEMENT_DAB", + "$SWWM_ACHIEVEMENT_HND", + "$SWWM_ACHIEVEMENT_GEPGUN", + "$SWWM_ACHIEVEMENT_FULLER", + "$SWWM_ACHIEVEMENT_PENE", + "$SWWM_ACHIEVEMENT_ACID", + "$SWWM_ACHIEVEMENT_SALT", + "$SWWM_ACHIEVEMENT_MEGA", + "$SWWM_ACHIEVEMENT_SANIC", + "$SWWM_ACHIEVEMENT_TELE", + "$SWWM_ACHIEVEMENT_BUNE", + "$SWWM_ACHIEVEMENT_BONK", + "$SWWM_ACHIEVEMENT_ANOM", + "$SWWM_ACHIEVEMENT_ANONE", + "$SWWM_ACHIEVEMENT_TETRIS", + "$SWWM_ACHIEVEMENT_PONG", + "$SWWM_ACHIEVEMENT_SNAKE", + "$SWWM_ACHIEVEMENT_SMB", + "$SWWM_ACHIEVEMENT_TYRIAN", + "$SWWM_ACHIEVEMENT_BOF" + }; + // has number in txt + static const int number[] = + { + SA_GCSANDWICH, + 0, // HDOOM + 0, // ONESTANDING + 0, // OOPSIE + SA_GHOST, + 0, // CLONK + SA_ALLITEMS, + SA_CONGA, + SA_EXPLOGUN, + SA_GRAVITY, + SA_FLIGHT, + 0, // CLIFFYB + SA_PAR, + 0, // ONEGUY + SA_GOLDEN, + SA_GIB, + SA_BARRIER, + SA_BOSSDASH, + SA_SNEEZE, + SA_FUEL, + SA_SLAYER, + 0, // BROCCOLIDOCCOLI + 0, // DIME + SA_STOMP, + 0, // CHEAT + 0, // GOD + SA_THRUWALL, + 0, // MASHIRO + SA_LEAD, + SA_LOVE, + SA_BUTTS, + SA_PLUSH, + SA_BUSTIN, + SA_MOTH, + 0, // IWAD + SA_BRAKE, + SA_RAGE, + 0, // ABORT + SA_PARRY, + SA_ALLKILLS, + SA_ALLSECRETS, + SA_REFLECT, + 0, // SEKIRO + SA_WAVE, + SA_FRIEND, + SA_SHOCK, + SA_BALLS, + SA_REFRESH, + SA_STEP, + SA_SUNNY, + SA_THICC, + 0, // EVERYTHING + 0, // ALLCOLL + SA_SLEMG, + 0, // DOSH + SA_JUMP, + SA_EZKILL, + 0, // LIGMA + 0, // YEET + 0, // MBF + 0, // LIGHTNING + 0, // DAKKA + SA_ROAST, + SA_DAB, + SA_HND, + SA_GEPGUN, + 0, // FULLER + SA_PENE, + SA_ACID, + 0, // SALT + 0, // MEGA + SA_SANIC, + 0, // TELE + SA_BUNE, + SA_BONK, + SA_ANOM, + 0, // ANONE + 0, // TETRIS + 0, // PONG + 0, // SNAKE + 0, // SMB + 0, // TYRIAN + 0 // BOF + }; + // is ignored (hide away achievements that can't be done yet) + static const bool ignoreme[] = + { + false, // GCSANDWICH + false, // HDOOM + false, // ONESTANDING + false, // OOPSIE + false, // GHOST + false, // CLONK + false, // ALLITEMS + false, // CONGA + false, // EXPLOGUN + false, // GRAVITY + false, // FLIGHT + false, // CLIFFYB + false, // PAR + false, // ONEGUY + false, // GOLDEN + false, // GIB + false, // BARRIER + false, // BOSSDASH + false, // SNEEZE + false, // FUEL + false, // SLAYER + false, // BROCCOLIDOCCOLI + false, // DIME + false, // STOMP + false, // CHEAT + false, // GOD + false, // THRUWALL + true, // MASHIRO + false, // LEAD + false, // LOVE + false, // BUTTS + false, // PLUSH + false, // BUSTIN + false, // MOTH + false, // IWAD + false, // BRAKE + false, // RAGE + false, // ABORT + false, // PARRY + false, // ALLKILLS + false, // ALLSECRETS + false, // REFLECT + false, // SEKIRO + false, // WAVE + false, // FRIEND + false, // SHOCK + false, // BALLS + false, // REFRESH + false, // STEP + false, // SUNNY + false, // THICC + false, // EVERYTHING + false, // ALLCOLL + false, // SLEMG + false, // DOSH + false, // JUMP + false, // EZKILL + false, // LIGMA + false, // YEET + false, // MBF + true, // LIGHTNING + true, // DAKKA + true, // ROAST + true, // DAB + true, // HND + true, // GEPGUN + true, // FULLER + true, // PENE + false, // ACID + false, // SALT + false, // MEGA + false, // SANIC + false, // TELE + false, // BUNE + false, // BONK + false, // ANOM + false, // ANONE + true, // TETRIS + true, // PONG + true, // SNAKE + true, // SMB + true, // TYRIAN + true // BOF + }; + // progress tracking cvar (if any) + static const Name pvar[] = + { + 'swwm_progress_gcsandwich', // GCSANDWICH + 'None', // HDOOM + 'None', // ONESTANDING + 'None', // OOPSIE + 'swwm_progress_ghost', // GHOST + 'None', // CLONK + 'swwm_progress_allitems', // ALLITEMS + 'swwm_progress_conga', // CONGA + 'swwm_progress_explogun', // EXPLOGUN + 'swwm_progress_gravity', // GRAVITY + 'swwm_progress_flight', // FLIGHT + 'None', // CLIFFYB + 'swwm_progress_par', // PAR + 'None', // ONEGUY + 'swwm_progress_golden', // GOLDEN + 'swwm_progress_gib', // GIB + 'swwm_progress_barrier', // BARRIER + 'swwm_progress_bossdash', // BOSSDASH + 'swwm_progress_sneeze', // SNEEZE + 'swwm_progress_fuel', // FUEL + 'swwm_progress_slayer', // SLAYER + 'None', // BROCCOLIDOCCOLI + 'None', // DIME + 'swwm_progress_stomp', // STOMP + 'None', // CHEAT + 'None', // GOD + 'swwm_progress_thruwall', // THRUWALL + 'None', // MASHIRO + 'swwm_progress_lead', // LEAD + 'swwm_progress_love', // LOVE + 'swwm_progress_butts', // BUTTS + 'swwm_progress_plush', // PLUSH + 'swwm_progress_bustin', // BUSTIN + 'swwm_progress_moth', // MOTH + 'None', // IWAD + 'swwm_progress_brake', // BRAKE + 'swwm_progress_rage', // RAGE + 'None', // ABORT + 'swwm_progress_parry', // PARRY + 'swwm_progress_allkills', // ALLKILLS + 'swwm_progress_allsecrets', // ALLSECRETS + 'swwm_progress_reflect', // REFLECT + 'None', // SEKIRO + 'swwm_progress_wave', // WAVE + 'swwm_progress_friend', // FRIEND + 'swwm_progress_shock', // SHOCK + 'swwm_progress_balls', // BALLS + 'swwm_progress_refresh', // REFRESH + 'swwm_progress_step', // STEP + 'swwm_progress_sunny', // SUNNY + 'swwm_progress_thicc', // THICC + 'None', // EVERYTHING + 'swwm_progress_allcoll', // ALLCOLL + 'swwm_progress_slemg', // SLEMG + 'swwm_progress_dosh', // DOSH + 'swwm_progress_jump', // JUMP + 'swwm_progress_ezkill', // EZKILL + 'None', // LIGMA + 'None', // YEET + 'None', // MBF + 'None', // LIGHTNING + 'swwm_progress_dakka', // DAKKA + 'swwm_progress_roast', // ROAST + 'swwm_progress_dab', // DAB + 'swwm_progress_hnd', // HND + 'swwm_progress_gepgun', // GEPGUN + 'None', // FULLER + 'swwm_progress_pene', // PENE + 'swwm_progress_acid', // ACID + 'None', // SALT + 'swwm_progress_mega', // MEGA + 'swwm_progress_sanic', // SANIC + 'None', // TELE + 'swwm_progress_bune', // BUNE + 'swwm_progress_bonk', // BONK + 'swwm_progress_anom', // ANOM + 'None', // ANONE + 'None', // TETRIS + 'None', // PONG + 'None', // SNAKE + 'None', // SMB + 'None', // TYRIAN + 'None' // BOF + }; + achievements.Clear(); + for ( int i=0; i)(AllActorClasses[i]); + if ( !c || (c == 'SWWMCollectible') ) continue; + nc++; + } + ac.maxval = nc; + } + else if ( vars[i] == 'swwm_achievement_dakka' ) ac.maxval = 60; + else if ( vars[i] == 'swwm_achievement_dosh' ) ac.maxval = 1000000000; + else if ( vars[i] == 'swwm_achievement_mega' ) ac.maxval = 1000000; + achievements.Push(ac); + } + AchievementUnknown = TexMan.CheckForTexture("graphics/Achievements/AchievementUnknown.png",TexMan.Type_Any); } // please don't look at this @@ -598,14 +1079,19 @@ Class DemolitionistMenu : GenericMenu } else if ( tabs[curtab] == TAB_STATS ) { - int cnt = 0; + int cnt = 0, num = 22; if ( sel1 == STAT_MAIN ) cnt = statlist.Size(); else if ( sel1 == STAT_KILLS ) cnt = sorted_mstats.Size(); else if ( sel1 == STAT_LEVEL ) cnt = filtered_lstats.Size(); - if ( (cnt > 22) && (sel0 < cnt-22) ) + else if ( sel1 == STAT_ACHIEVEMENT ) + { + cnt = achievements.Size(); + num = 7; + } + if ( (cnt > num) && (sel0 < cnt-num) ) { MenuSound("menu/demoscroll"); ofs0 = ++sel0; @@ -1569,13 +2055,18 @@ Class DemolitionistMenu : GenericMenu } // are we clicking where the scrollbar should be? if ( mpos.x < 632 ) return res; - int cnt = 0; + int cnt = 0, num = 22; if ( sel1 == STAT_MAIN ) cnt = statlist.Size(); else if ( sel1 == STAT_KILLS ) cnt = stats.mstats.Size(); else if ( sel1 == STAT_LEVEL ) cnt = filtered_lstats.Size(); - if ( cnt <= 28 ) return res; // no scrollbar + else if ( sel1 == STAT_ACHIEVEMENT ) + { + cnt = achievements.Size(); + num = 7; + } + if ( cnt <= num ) return res; // no scrollbar // calculate offset - int szr = cnt-28; + int szr = cnt-num; int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr); if ( step != sel0 ) MenuSound("menu/demoscroll"); ofs0 = sel0 = step; @@ -1781,13 +2272,18 @@ Class DemolitionistMenu : GenericMenu } else if ( tabs[curtab] == TAB_STATS ) { - int cnt = 0; + int cnt = 0, num = 22; if ( sel1 == STAT_MAIN ) cnt = statlist.Size(); else if ( sel1 == STAT_KILLS ) cnt = stats.mstats.Size(); else if ( sel1 == STAT_LEVEL ) cnt = filtered_lstats.Size(); - if ( cnt <= 22 ) return res; // no scrollbar + else if ( sel1 == STAT_ACHIEVEMENT ) + { + cnt = achievements.Size(); + num = 7; + } + if ( cnt <= num ) return res; // no scrollbar // calculate offset - int szr = cnt-22; + int szr = cnt-num; int step = clamp(rnd((mpos.y-24.)/(353./szr)),0,szr); if ( step != sel0 ) MenuSound("menu/demoscroll"); ofs0 = sel0 = step; @@ -2154,6 +2650,68 @@ Class DemolitionistMenu : GenericMenu qsort_collectible(a,p+1,h); } + private bool CmpAchievement( MenuAchievement a, MenuAchievement b ) + { + bool adone = !!(a.state.GetInt()), bdone = !!(b.state.GetInt()); + double afactor = adone?1.:0., bfactor = bdone?1.:0.; + if ( a.progress ) + { + int cur = min(a.progress.GetInt(),a.maxval); + afactor = cur/double(a.maxval); + } + if ( b.progress ) + { + int cur = min(b.progress.GetInt(),b.maxval); + bfactor = cur/double(b.maxval); + } + if ( adone && bdone ) + { + // alphabetic sort + String tag1 = StringTable.Localize(a.tag), + tag2 = StringTable.Localize(b.tag); + return tag1 > tag2; + } + if ( !adone && !bdone ) + { + // progress sort? + if ( afactor != bfactor ) + return afactor < bfactor; + // alphabetic sort + String tag1 = StringTable.Localize(a.tag), + tag2 = StringTable.Localize(b.tag); + return tag1 > tag2; + } + // state sort + return bdone; + } + + private int partition_achievements( Array a, int l, int h ) + { + MenuAchievement pv = a[h]; + int i = (l-1); + for ( int j=l; j<=(h-1); j++ ) + { + if ( CmpAchievement(pv,a[j]) ) + { + i++; + MenuAchievement tmp = a[j]; + a[j] = a[i]; + a[i] = tmp; + } + } + MenuAchievement tmp = a[h]; + a[h] = a[i+1]; + a[i+1] = tmp; + return i+1; + } + private void qsort_achievements( Array a, int l, int h ) + { + if ( l >= h ) return; + int p = partition_achievements(a,l,h); + qsort_achievements(a,l,p-1); + qsort_achievements(a,p+1,h); + } + override void Ticker() { Super.Ticker(); @@ -2585,6 +3143,8 @@ Class DemolitionistMenu : GenericMenu curlstat.suck = level.sucktime; filtered_lstats.Push(curlstat); } + else if ( (tabs[curtab] == TAB_STATS) && (sel1 == STAT_ACHIEVEMENT) ) + qsort_achievements(achievements,0,achievements.Size()-1); // ui->play transaction checks for ( int i=0; i= 360 ) break; + let a = achievements[i]; + bool completed = !!a.state.GetInt(); + bool hasprogress = (a.progress && a.progress.GetInt()); + Screen.DrawTexture((!completed&&!hasprogress)?AchievementUnknown:a.icon,false,origin.x+xx+1,origin.y+yy+1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_FillColor,(!completed&&!hasprogress)?Color(8,8,8):Color(16,16,16)); + Screen.DrawTexture((!completed&&!hasprogress)?AchievementUnknown:a.icon,false,origin.x+xx,origin.y+yy,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Desaturate,(!completed)*255,DTA_ColorOverlay,completed?Color(0,0,0,0):hasprogress?Color(96,0,0,0):Color(192,0,0,0)); + // progress bar + if ( a.progress ) + { + if ( completed ) str = SWWMUtility.BlockBar(a.maxval,a.maxval,barsz,Font.CR_GOLD,Font.CR_BLACK); + else str = SWWMUtility.BlockBar(a.progress.GetInt(),a.maxval,barsz,Font.CR_DARKGRAY,Font.CR_BLACK); + Screen.DrawText(TewiFont,Font.CR_UNTRANSLATED,origin.x+xx,origin.y+yy+34,str,DTA_Spacing,-5,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); + if ( completed ) str = String.Format("%s / %s",SWWMUtility.ThousandsNum(a.maxval),SWWMUtility.ThousandsNum(a.maxval)); + else str = String.Format("%s / %s",SWWMUtility.ThousandsNum(a.progress.GetInt()),SWWMUtility.ThousandsNum(a.maxval)); + int ox = (barsz-MiniwiFont.StringWidth(str))/2; + Screen.DrawText(MiniwiFont,Font.CR_WHITE,origin.x+xx+ox,origin.y+yy+38,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); + } + else + { + str = SWWMUtility.BlockBar(completed,1,barsz,Font.CR_GOLD,Font.CR_BLACK); + Screen.DrawText(TewiFont,Font.CR_UNTRANSLATED,origin.x+xx,origin.y+yy+34,str,DTA_Spacing,-5,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); + } + // the text itself + str = a.num?String.Format(StringTable.Localize(a.txt),a.num):StringTable.Localize(a.txt); + if ( !completed && !hasprogress ) SWWMUtility.ObscureText(str,(gametic/3)+i*2); + BrokenLines l = fnt2.BreakLines(str,txtsz); + str = StringTable.Localize(a.tag); + if ( !completed && !hasprogress ) SWWMUtility.ObscureText(str,(gametic/3)+i*2+1); + int oy = (32-(14+(9*l.Count())))/2; + Screen.DrawText(fnt,completed?Font.CR_GREEN:Font.CR_DARKGRAY,origin.x+xx+36,origin.y+yy+oy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); + for ( int j=0; j 7 ) + { + Screen.DrawTexture(WindowSeparator,false,origin.x+631,origin.y+14,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); + xx = 634; + int szr = cnt-7; + yy = floor(ofs*(353./szr))+17; + Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,"▮",DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); + } } } else if ( (tabs[curtab] == TAB_INVENTORY) || ((tabs[curtab] == TAB_TRADING) && sub && (sel0 != -1)) ) diff --git a/zscript/swwm_statichandler.zsc b/zscript/swwm_statichandler.zsc index 133a04941..788cc71a6 100644 --- a/zscript/swwm_statichandler.zsc +++ b/zscript/swwm_statichandler.zsc @@ -19,6 +19,7 @@ Class SWWMStaticHandler : StaticEventHandler String mpver[MAXPLAYERS]; int checktic; ui bool mpsent, checked; + int maptime; override void NewGame() { @@ -33,8 +34,14 @@ Class SWWMStaticHandler : StaticEventHandler SWWMHandler.ClearAllShaders(players[consoleplayer]); } + override void WorldTick() + { + maptime++; + } + override void WorldLoaded( WorldEvent e ) { + maptime = 0; if ( e.IsSavegame || e.IsReopen ) { // restore underwater sounds for players @@ -134,12 +141,28 @@ Class SWWMStaticHandler : StaticEventHandler if ( verstr != StringTable.Localize("$SWWM_SHORTVER") ) mptaint[e.Player] = true; } + else if ( e.Name.Left(16) ~== "swwmachievement." ) + { + let c = Actor.Spawn("PartyTime",players[e.Args[0]].mo.pos); + c.bSTANDSTILL = true; + if ( e.Args[0] == consoleplayer ) + { + S_StartSound("misc/achievement",CHAN_ITEM,CHANF_UI|CHANF_OVERLAP); + S_StartSound("misc/achievement2",CHAN_VOICE,CHANF_UI|CHANF_OVERLAP); + } + else + { + Console.Printf(String.Format(StringTable.Localize("$SWWM_CHEEVOREM"),players[e.Args[0]].GetUserName(),StringTable.Localize(e.Name.Mid(16)))); + c.A_StartSound("misc/achievement",CHAN_ITEM,CHANF_OVERLAP); + c.A_StartSound("misc/achievement2",CHAN_ITEM,CHANF_OVERLAP); + } + } } override void PostUiTick() { - // TODO achievement update code would go in here if ( gamestate != GS_LEVEL ) return; + CheckAllAchievements(); if ( !mpsent ) { EventHandler.SendNetworkEvent("swwmversion."..StringTable.Localize("$SWWM_SHORTVER")); @@ -215,6 +238,7 @@ Class SWWMStaticHandler : StaticEventHandler wasinmap = false; if ( timer == 1 ) { + if ( swwm_achievement_abort < 1 ) CVar.FindCVar('swwm_achievement_abort').SetInt(1); Console.Printf("\cfOopsie Woopsie!\c-"); let hnd = SWWMBrutalHandler(StaticEventHandler.Find("SWWMBrutalHandler")); if ( hnd && hnd.detected ) diff --git a/zscript/swwm_thinkers_player.zsc b/zscript/swwm_thinkers_player.zsc index a752c88c5..d999cdb73 100644 --- a/zscript/swwm_thinkers_player.zsc +++ b/zscript/swwm_thinkers_player.zsc @@ -69,8 +69,9 @@ Class SWWMStats : Thinker else if ( (inflictor is 'DragonBreathArm') || ((inflictor is 'SaltImpact') && !inflictor.Args[0]) || ((inflictor is 'SaltBeam') && !inflictor.Args[1]) || (inflictor is 'CorrodeDebuff') || (inflictor is 'CorrosiveFlechette') || ((inflictor is 'TheBall') && !inflictor.special1) || (inflictor is 'GoldenImpact') || (inflictor is 'GoldenSubImpact') || (inflictor is 'GoldenSubSubImpact') ) which = 'Spreadgun'; else if ( ((inflictor is 'SaltImpact') && inflictor.Args[0]) || ((inflictor is 'SaltBeam') && inflictor.Args[1]) || ((inflictor is 'TheBall') && inflictor.special1) ) which = 'Wallbuster'; else if ( (inflictor is 'EvisceratorChunk') || (inflictor is 'EvisceratorProj') ) which = 'Eviscerator'; - else if ( (inflictor is 'HellblazerRavagerArm') || (inflictor is 'HellblazerWarheadArm') ) which = 'Hellblazer'; - else if ( (inflictor is 'BigBiospark') || (inflictor is 'BiosparkBall') || (inflictor is 'BiosparkBeamImpact') || (inflictor is 'BiosparkComboImpact') || (inflictor is 'BiosparkComboImpactSub') || (inflictor is 'BiosparkBeam') || (inflictor is 'BiosparkArc') ) which = 'Sparkster'; + else if ( (inflictor is 'HellblazerMissile') || (inflictor is 'HellblazerRavagerArm') || (inflictor is 'HellblazerWarheadArm') ) which = 'Hellblazer'; + else if ( (inflictor is 'BigBiospark') || (inflictor is 'BiosparkBall') || (inflictor is 'BiosparkBeamImpact') || (inflictor is 'BiosparkComboImpact') || (inflictor is 'BiosparkComboImpactSub') || (inflictor is 'BiosparkBeam') || (inflictor is 'BiosparkArc') || (inflictor is 'BiosparkCore') ) which = 'Sparkster'; + else if ( (inflictor is 'SilverAirRip') || (inflictor is 'SilverAirRip2') || (inflictor is 'SilverImpact') || (inflictor is 'FatChodeImpact') || (inflictor is 'FatChodeExplosionArm') ) which = 'SilverBullet'; else if ( (inflictor is 'CandyBeam') || (inflictor is 'CandyPop') || (inflictor is 'CandyMagArm') || (inflictor is 'CandyGunProj') || (inflictor is 'CandyMagProj') || (inflictor is 'CandyBulletImpact') ) which = 'CandyGun'; else if ( (inflictor is 'YnykronBeam') || (inflictor is 'YnykronImpact') || (inflictor is 'YnykronSingularity') || (inflictor is 'YnykronCloud') || (inflictor is 'YnykronVoidBeam') || (inflictor is 'YnykronLightningArc') || (inflictor is 'YnykronLightningImpact') ) which = 'Ynykron'; else if ( (inflictor is 'Demolitionist') || (inflictor is 'DemolitionistShockwave') || (inflictor is 'DemolitionistRadiusShockwave') || (inflictor is 'SWWMGesture') diff --git a/zscript/utility/swwm_utility.zsc b/zscript/utility/swwm_utility.zsc index 2458cdf42..0751ed5a6 100644 --- a/zscript/utility/swwm_utility.zsc +++ b/zscript/utility/swwm_utility.zsc @@ -107,6 +107,47 @@ Class SWWMUtility return str; } + static clearscope String BlockBar( int a, int b, int width, int acol, int bcol ) + { + String str = ""; + int blocks = clamp(int(a/double(b)*width),0,width); + int eblocks = width-blocks; + if ( blocks ) + { + str.AppendCharacter(0x1C); + str.AppendCharacter(0x41+acol); + } + for ( int i=0; i 80) ) continue; + if ( !((SWWMUtility.ValidProjectile(a) && (a.target != master)) || a.bSKULLFLY) || a.bTHRUACTORS || (level.Vec3Diff(a.pos,pos).length() > 80) ) continue; Vector3 vdir = a.vel; Vector3 dir = level.Vec3Diff(master.Vec2OffsetZ(0,0,pos.z),a.pos).unit(); Vector3 hdir = dir; diff --git a/zscript/weapons/swwm_deepdarkimpact.zsc b/zscript/weapons/swwm_deepdarkimpact.zsc index c367ae08d..b0a8d19be 100644 --- a/zscript/weapons/swwm_deepdarkimpact.zsc +++ b/zscript/weapons/swwm_deepdarkimpact.zsc @@ -213,7 +213,7 @@ Class DeepImpact : SWWMWeapon Actor m; while ( m = Actor(ti.Next()) ) { - if ( !(m.bMISSILE && !m.IsZeroDamage() && (m.target != self)) ) continue; + if ( !(SWWMUtility.ValidProjectile(m) && (m.target != self)) ) continue; Vector3 rdir = level.Vec3Diff(origin,m.pos); double rdist = rdir.length(); if ( rdist <= 0. ) continue;