From 8176b21b8c7654fe0271d5ce65c1b9bf9ee70df4 Mon Sep 17 00:00:00 2001 From: Marisa Kirisame Date: Mon, 20 Sep 2021 19:22:42 +0200 Subject: [PATCH] Achievement system overhaul. Continuin the menu rewrite. --- FuturePlans.md | 5 + cvarinfo.achievements | 143 --------- cvarinfo.base | 8 +- filter/game-doom/cvarinfo.doomachievements | 30 -- .../game-heretic/cvarinfo.hereticachievements | 21 -- filter/game-hexen/cvarinfo.hexenachievements | 10 - graphics/KBase/FrameTex.png | Bin 0 -> 123 bytes graphics/KBase/HSepTex.png | Bin 0 -> 101 bytes graphics/KBase/LibraryTabSeparator.png | Bin 101 -> 0 bytes graphics/KBase/LibraryTabSeparatorJP.png | Bin 102 -> 0 bytes graphics/KBase/TabSeparator.png | Bin 95 -> 0 bytes graphics/KBase/VSepTex.png | Bin 0 -> 101 bytes graphics/KBase/WindowSeparator.png | Bin 102 -> 0 bytes graphics/KBase/WindowSeparatorH.png | Bin 105 -> 0 bytes language.version | 4 +- zscript/handler/swwm_handler_cheats.zsc | 2 +- zscript/handler/swwm_handler_damage.zsc | 30 +- zscript/handler/swwm_handler_replacements.zsc | 2 +- zscript/handler/swwm_handler_worldload.zsc | 18 +- zscript/handler/swwm_handler_worldtick.zsc | 4 +- .../swwm_statichandler_achievements.zsc | 278 ++++++++++++++++-- zscript/hud/swwm_hud.zsc | 2 +- zscript/items/swwm_ammoitems.zsc | 1 + zscript/items/swwm_armor.zsc | 2 +- zscript/items/swwm_collectibles.zsc | 2 +- zscript/items/swwm_health.zsc | 4 +- zscript/items/swwm_powerups.zsc | 26 +- zscript/kbase/swwm_kbase.zsc | 97 +++++- zscript/menu/swwm_achievementmenu.zsc | 87 +++--- zscript/swwm_gesture.zsc | 4 +- zscript/swwm_gesture_fx.zsc | 4 +- zscript/swwm_handler.zsc | 2 +- zscript/swwm_monsters.zsc | 2 +- zscript/swwm_player.zsc | 34 +-- zscript/swwm_statichandler.zsc | 56 ++-- zscript/swwm_thinkers.zsc | 2 +- zscript/swwm_thinkers_player.zsc | 6 +- zscript/utility/swwm_utility.zsc | 161 +++------- zscript/weapons/swwm_baseweapon_melee.zsc | 6 +- zscript/weapons/swwm_blazeit_fx.zsc | 2 +- zscript/weapons/swwm_cbt.zsc | 2 +- zscript/weapons/swwm_cbt_fx.zsc | 2 +- zscript/weapons/swwm_danmaku_fx.zsc | 2 +- .../weapons/swwm_deathlydeathcannon_fx.zsc | 12 +- zscript/weapons/swwm_deepdarkimpact.zsc | 2 +- zscript/weapons/swwm_shot.zsc | 2 +- zscript/weapons/swwm_shot_fx.zsc | 6 +- zscript/weapons/swwm_sparkyboi_fx.zsc | 2 +- zscript/weapons/swwm_splode.zsc | 4 +- zscript/weapons/swwm_splode_fx.zsc | 4 +- zscript/weapons/swwm_tastytreat_fx.zsc | 2 +- zscript/weapons/swwm_thiccboolet.zsc | 4 +- zscript/weapons/swwm_thiccboolet_fx.zsc | 8 +- 53 files changed, 587 insertions(+), 520 deletions(-) delete mode 100644 cvarinfo.achievements delete mode 100644 filter/game-doom/cvarinfo.doomachievements delete mode 100644 filter/game-heretic/cvarinfo.hereticachievements delete mode 100644 filter/game-hexen/cvarinfo.hexenachievements create mode 100644 graphics/KBase/FrameTex.png create mode 100644 graphics/KBase/HSepTex.png delete mode 100644 graphics/KBase/LibraryTabSeparator.png delete mode 100644 graphics/KBase/LibraryTabSeparatorJP.png delete mode 100644 graphics/KBase/TabSeparator.png create mode 100644 graphics/KBase/VSepTex.png delete mode 100644 graphics/KBase/WindowSeparator.png delete mode 100644 graphics/KBase/WindowSeparatorH.png diff --git a/FuturePlans.md b/FuturePlans.md index 28029c790..57d875f61 100644 --- a/FuturePlans.md +++ b/FuturePlans.md @@ -9,6 +9,11 @@ I REALLY need to do this, it's starting to become very problematic to maintain t - Smooth scrolling, better mouse input - Much cleaner code, easier maintenance and extension - Modular design, add-on tab support +* **Achievement CVar Compression:** + - Switch achievements to use a dictionary, rather than individual CVars + - Potentially more robust (maybe?) + - Harder to tamper with + - Can keep state in a local Dictionary object to avoid excess CVar access ## 1.3 update *(The Second Batch)*: diff --git a/cvarinfo.achievements b/cvarinfo.achievements deleted file mode 100644 index 3e38b75af..000000000 --- a/cvarinfo.achievements +++ /dev/null @@ -1,143 +0,0 @@ -// shared achievements - -// cross-session achievement cvars (0: locked, 1: unlocked, 2: notified) -nosave int swwm_achievement_acid = 0; -nosave int swwm_achievement_allcoll = 0; -nosave int swwm_achievement_anom = 0; -nosave int swwm_achievement_anone = 0; -nosave int swwm_achievement_balls = 0; -nosave int swwm_achievement_bonk = 0; -nosave int swwm_achievement_bossdash = 0; -nosave int swwm_achievement_brake = 0; -nosave int swwm_achievement_bune = 0; -nosave int swwm_achievement_bustin = 0; -nosave int swwm_achievement_butts = 0; -nosave int swwm_achievement_candy = 0; -nosave int swwm_achievement_cheat = 0; -nosave int swwm_achievement_clonk = 0; -nosave int swwm_achievement_conga = 0; -nosave int swwm_achievement_crush = 0; -nosave int swwm_achievement_cum = 0; -nosave int swwm_achievement_dab = 0; -nosave int swwm_achievement_dakka = 0; -nosave int swwm_achievement_deadeye = 0; -nosave int swwm_achievement_deva = 0; -nosave int swwm_achievement_dime = 0; -nosave int swwm_achievement_divine = 0; -nosave int swwm_achievement_dosh = 0; -nosave int swwm_achievement_everything = 0; -nosave int swwm_achievement_ezkill = 0; -nosave int swwm_achievement_fisto = 0; -nosave int swwm_achievement_flight = 0; -nosave int swwm_achievement_friend = 0; -nosave int swwm_achievement_fuel = 0; -nosave int swwm_achievement_fuller = 0; -nosave int swwm_achievement_gcsandwich = 0; -nosave int swwm_achievement_gepgun = 0; -nosave int swwm_achievement_ghost = 0; -nosave int swwm_achievement_gib = 0; -nosave int swwm_achievement_golden = 0; -nosave int swwm_achievement_grenade = 0; -nosave int swwm_achievement_hnd = 0; -nosave int swwm_achievement_hurry = 0; -nosave int swwm_achievement_ice = 0; -nosave int swwm_achievement_jump = 0; -nosave int swwm_achievement_lead = 0; -nosave int swwm_achievement_lightning = 0; -nosave int swwm_achievement_ligma = 0; -nosave int swwm_achievement_love = 0; -nosave int swwm_achievement_mashiro = 0; -nosave int swwm_achievement_mega = 0; -nosave int swwm_achievement_moth = 0; -nosave int swwm_achievement_oneguy = 0; -nosave int swwm_achievement_onehp = 0; -nosave int swwm_achievement_oopsie = 0; -nosave int swwm_achievement_parry = 0; -nosave int swwm_achievement_pene = 0; -nosave int swwm_achievement_plasma = 0; -nosave int swwm_achievement_plush = 0; -nosave int swwm_achievement_rage = 0; -nosave int swwm_achievement_rail = 0; -nosave int swwm_achievement_reflect = 0; -nosave int swwm_achievement_refresh = 0; -nosave int swwm_achievement_roast = 0; -nosave int swwm_achievement_salt = 0; -nosave int swwm_achievement_sanic = 0; -nosave int swwm_achievement_sekiro = 0; -nosave int swwm_achievement_shame = 0; -nosave int swwm_achievement_shock = 0; -nosave int swwm_achievement_slayer = 0; -nosave int swwm_achievement_slemg = 0; -nosave int swwm_achievement_sneeze = 0; -nosave int swwm_achievement_spark = 0; -nosave int swwm_achievement_step = 0; -nosave int swwm_achievement_stomp = 0; -nosave int swwm_achievement_sunny = 0; -nosave int swwm_achievement_tele = 0; -nosave int swwm_achievement_tender = 0; -nosave int swwm_achievement_thicc = 0; -nosave int swwm_achievement_thruwall = 0; -nosave int swwm_achievement_travel = 0; -nosave int swwm_achievement_wantdie = 0; -nosave int swwm_achievement_wave = 0; -// cross-session progress cvars -nosave int swwm_progress_acid = 0; -nosave int swwm_progress_allcoll = 0; -nosave int swwm_progress_anom = 0; -nosave int swwm_progress_balls = 0; -nosave int swwm_progress_bonk = 0; -nosave int swwm_progress_bossdash = 0; -nosave int swwm_progress_brake = 0; -nosave int swwm_progress_bune = 0; -nosave int swwm_progress_bustin = 0; -nosave int swwm_progress_butts = 0; -nosave int swwm_progress_candy = 0; -nosave int swwm_progress_conga = 0; -nosave int swwm_progress_cum = 0; -nosave int swwm_progress_dab = 0; -nosave int swwm_progress_dakka = 0; -nosave int swwm_progress_deadeye = 0; -nosave int swwm_progress_deva = 0; -nosave int swwm_progress_divine = 0; -nosave int swwm_progress_dosh = 0; -nosave int swwm_progress_ezkill = 0; -nosave int swwm_progress_fisto = 0; -nosave int swwm_progress_flight = 0; -nosave int swwm_progress_friend = 0; -nosave float swwm_progress_fuel = 0; // this one needs to be float -nosave int swwm_progress_gcsandwich = 0; -nosave int swwm_progress_gepgun = 0; -nosave int swwm_progress_ghost = 0; -nosave int swwm_progress_gib = 0; -nosave int swwm_progress_golden = 0; -nosave int swwm_progress_grenade = 0; -nosave int swwm_progress_hnd = 0; -nosave int swwm_progress_ice = 0; -nosave int swwm_progress_jump = 0; -nosave int swwm_progress_lead = 0; -nosave int swwm_progress_love = 0; -nosave int swwm_progress_mega = 0; -nosave int swwm_progress_moth = 0; -nosave int swwm_progress_onehp = 0; -nosave int swwm_progress_parry = 0; -nosave int swwm_progress_pene = 0; -nosave int swwm_progress_plasma = 0; -nosave int swwm_progress_plush = 0; -nosave int swwm_progress_rage = 0; -nosave int swwm_progress_rail = 0; -nosave int swwm_progress_reflect = 0; -nosave int swwm_progress_refresh = 0; -nosave int swwm_progress_roast = 0; -nosave int swwm_progress_sanic = 0; -nosave int swwm_progress_shock = 0; -nosave int swwm_progress_slayer = 0; -nosave int swwm_progress_slemg = 0; -nosave int swwm_progress_sneeze = 0; -nosave int swwm_progress_spark = 0; -nosave int swwm_progress_step = 0; -nosave int swwm_progress_stomp = 0; -nosave int swwm_progress_sunny = 0; -nosave int swwm_progress_tender = 0; -nosave int swwm_progress_thicc = 0; -nosave int swwm_progress_thruwall = 0; -nosave float swwm_progress_travel = 0; // also needs to be float diff --git a/cvarinfo.base b/cvarinfo.base index fbe60dc3e..7bd1732d4 100644 --- a/cvarinfo.base +++ b/cvarinfo.base @@ -3,7 +3,7 @@ user string swwm_voicetype = "default"; // voice for your demolitionist nosave float swwm_flashstrength = 1.0; // strength of screen flashes nosave int swwm_hudmargin = 10; // margin around fullscreen hud elements nosave int swwm_maxshown = 4; // max messages to show normally -nosave int swwm_maxshownbig = 10; // max messages to show when chatting +nosave int swwm_maxshownbig = 10; // max messages to show when chatting nosave int swwm_maxpickup = 5; // total pickup messages visible nosave int swwm_mutevoice = 0; // mute demolitionist voice // 0 - none @@ -24,7 +24,7 @@ user bool swwm_autouseammo = true; // automatically use ammo fabricators when p server int swwm_enforceautousearmor = 0; // 1: server enforces auto use, -1: server enforces no auto use, 0: server respects user setting server int swwm_enforceautousehealth = 0; // likewise for health server int swwm_enforceautouseammo = 0; // likewise for fabricators -nosave bool swwm_targeter = true; // show targeter healthbars +nosave bool swwm_targeter = true; // show targeter healthbars nosave bool swwm_targettags = true; // show enemy tags above healthbars nosave bool swwm_healthnums = true; // show damage/healing numbers nosave bool swwm_scorenums = true; // show score numbers @@ -158,4 +158,6 @@ nosave color swwm_mm_yourcolor = "80 ff 00"; server noarchive bool swwm_iseriouslywanttoplaythiswithbd = false; // self-explanatory -nosave int swwm_playtime = 0; // total playtime in seconds +nosave int swwm_playtime = 0; // total playtime in seconds +nosave string swwm_achievementstate = ""; // stores dictionary with all achievement states +nosave string swwm_achievementprogress = ""; // stores dictionary with all achievement progress diff --git a/filter/game-doom/cvarinfo.doomachievements b/filter/game-doom/cvarinfo.doomachievements deleted file mode 100644 index 762a47dd0..000000000 --- a/filter/game-doom/cvarinfo.doomachievements +++ /dev/null @@ -1,30 +0,0 @@ -// doom-exclusive achievements - -// cross-session achievement cvars (0: locked, 1: unlocked, 2: notified) -nosave int swwm_achievement_allitems = 0; -nosave int swwm_achievement_allkills = 0; -nosave int swwm_achievement_allsecrets = 0; -nosave int swwm_achievement_barrel = 0; -nosave int swwm_achievement_barrier = 0; -nosave int swwm_achievement_baseball = 0; -nosave int swwm_achievement_blaze = 0; -nosave int swwm_achievement_cliffyb = 0; -nosave int swwm_achievement_cybully = 0; -nosave int swwm_achievement_doodle = 0; -nosave int swwm_achievement_keen = 0; -nosave int swwm_achievement_mbf = 0; -nosave int swwm_achievement_nice = 0; -nosave int swwm_achievement_onestanding = 0; -nosave int swwm_achievement_par = 0; -nosave int swwm_achievement_peace = 0; -nosave int swwm_achievement_trash = 0; -nosave int swwm_achievement_untouchable = 0; -nosave int swwm_achievement_yeet = 0; -// cross-session progress cvars -nosave int swwm_progress_allitems = 0; -nosave int swwm_progress_allkills = 0; -nosave int swwm_progress_allsecrets = 0; -nosave int swwm_progress_barrel = 0; -nosave int swwm_progress_barrier = 0; -nosave int swwm_progress_doodle = 0; -nosave int swwm_progress_par = 0; diff --git a/filter/game-heretic/cvarinfo.hereticachievements b/filter/game-heretic/cvarinfo.hereticachievements deleted file mode 100644 index 1627939dd..000000000 --- a/filter/game-heretic/cvarinfo.hereticachievements +++ /dev/null @@ -1,21 +0,0 @@ -// heretic-exclusive achievements - -// cross-session achievement cvars (0: locked, 1: unlocked, 2: notified) -nosave int swwm_achievement_allitems = 0; -nosave int swwm_achievement_allkills = 0; -nosave int swwm_achievement_allsecrets = 0; -nosave int swwm_achievement_blaze = 0; -nosave int swwm_achievement_cliffyb = 0; -nosave int swwm_achievement_gravity = 0; -nosave int swwm_achievement_nice = 0; -nosave int swwm_achievement_onestanding = 0; -nosave int swwm_achievement_peace = 0; -nosave int swwm_achievement_sneaky = 0; -nosave int swwm_achievement_tornado = 0; -nosave int swwm_achievement_untouchable = 0; -// cross-session progress cvars -nosave int swwm_progress_allitems = 0; -nosave int swwm_progress_allkills = 0; -nosave int swwm_progress_allsecrets = 0; -nosave int swwm_progress_gravity = 0; -nosave int swwm_progress_sneaky = 0; diff --git a/filter/game-hexen/cvarinfo.hexenachievements b/filter/game-hexen/cvarinfo.hexenachievements deleted file mode 100644 index 170bd8b9c..000000000 --- a/filter/game-hexen/cvarinfo.hexenachievements +++ /dev/null @@ -1,10 +0,0 @@ -// hexen-exclusive achievements - -// cross-session achievement cvars (0: locked, 1: unlocked, 2: notified) -nosave int swwm_achievement_gravity = 0; -nosave int swwm_achievement_kancho = 0; -nosave int swwm_achievement_puzzle = 0; -nosave int swwm_achievement_sneaky = 0; -// cross-session progress cvars -nosave int swwm_progress_gravity = 0; -nosave int swwm_progress_sneaky = 0; diff --git a/graphics/KBase/FrameTex.png b/graphics/KBase/FrameTex.png new file mode 100644 index 0000000000000000000000000000000000000000..79a975e649cc8ee283d7bdbd8e7bfc09074a316f GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0y~yU|<1Z7G?$phUojvz6=Zuq5(c3uK7i|3H|#W66zHU z90Vj3ICumY7#L*Q=9DrpFff(``2{mLJiC#`z`!8l>Eal|aXneUC?TLA*?==S!JC8nhXpKLIFM@t_l779TMsl3>*X` z6gYSU7#J94Si2r(U|`_$ba4#fxSkwPmXHv_z`%H&q1CC@fscWKfx*+&&t;ucLK6U! COcd$> literal 0 HcmV?d00001 diff --git a/graphics/KBase/LibraryTabSeparator.png b/graphics/KBase/LibraryTabSeparator.png deleted file mode 100644 index 614fc728ea5621977faf4ddae0b70778a2f0b90a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101 zcmeAS@N?(olHy`uVBq!ia0y~yV5nnYU|?clW?*2*d0WcJz`(#C;1lA?!6P6bp`c*k z;E+(C(7&HSEPfRO1B0Nai(?3fY;usu5*7{v%|JGW<+?lz%>{KgGB7YOc)I$ztaD0e F0sxnV6nX#v diff --git a/graphics/KBase/LibraryTabSeparatorJP.png b/graphics/KBase/LibraryTabSeparatorJP.png deleted file mode 100644 index be067083099040a0152210bf17070119babc046a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102 zcmeAS@N?(olHy`uVBq!ia0y~yU^vIXz`(@9%)r3#Ncx`z0|NtpfKP}k2akY&go1*B zgF`}nLjQgSvG`RC3=Be^E{-7_vdKXrOV|Yxf)?>JFfjFq%zT+Lv6q2?fx*+&&t;uc GLK6V|VixQG diff --git a/graphics/KBase/TabSeparator.png b/graphics/KBase/TabSeparator.png deleted file mode 100644 index b22e2151543a78b1275aa098a08990bdd8df93b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ckVBq5bkzHa@91IK$YMw5RAsp9}0}Kj0Ufe%_ v=D>ji2el6zIRF9y0|SFlfKP~PLjQh;gn9)7 z2LTBM4jusp28J2du7?>I82CJ0978y+CkG@Lq!chQFjg~639>yF&%nUI;OXk;vd$@? F2>{+J7B>I@ literal 0 HcmV?d00001 diff --git a/graphics/KBase/WindowSeparator.png b/graphics/KBase/WindowSeparator.png deleted file mode 100644 index 295b8cbab7180f0396ed164e950c994b33425c2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ckU@T!_W?*3WJ>_dX0|NtpfKP}k2akY&go1*B zgF`}nLjQgSvG`RC3=Be^E{-7@=aT~x1>{;67tC;0V+b{qo}0h!dj@fkt@ diff --git a/graphics/KBase/WindowSeparatorH.png b/graphics/KBase/WindowSeparatorH.png deleted file mode 100644 index 76c43358285225dc15f0ffb24e6a8ac19e8262c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sU|?clW?*2jVkvmVz`(#C;1lA?!6P6bp`c*k z;E+(C(7&HSEPfRO1B0lii(`m{WO9&*466tOquSCy2SEmgi&yNgbXJIjGcYhPc)I$z JtaD0e0s!Jt78d{j diff --git a/language.version b/language.version index ab9fe567d..12b0afad2 100644 --- a/language.version +++ b/language.version @@ -1,3 +1,3 @@ [default] -SWWM_MODVER="\chSWWM \czGZ\c- \cw1.2pre \cu(Sat 18 Sep 14:20:11 CEST 2021)\c-"; -SWWM_SHORTVER="\cw1.2pre \cu(2021-09-18 14:20:11)\c-"; +SWWM_MODVER="\chSWWM \czGZ\c- \cw1.2pre \cu(Mon 20 Sep 19:22:42 CEST 2021)\c-"; +SWWM_SHORTVER="\cw1.2pre \cu(2021-09-20 19:22:42)\c-"; diff --git a/zscript/handler/swwm_handler_cheats.zsc b/zscript/handler/swwm_handler_cheats.zsc index 558128693..b45acdba8 100644 --- a/zscript/handler/swwm_handler_cheats.zsc +++ b/zscript/handler/swwm_handler_cheats.zsc @@ -449,7 +449,7 @@ extend Class SWWMHandler StatusBar.AttachMessage(m,-1232); CVar.FindCVar('swwm_oldcheat').SetBool(true); } - SWWMUtility.MarkAchievement('swwm_achievement_cheat',players[consoleplayer]); + SWWMUtility.MarkAchievement("cheat",players[consoleplayer]); if ( SWWMUtility.CheatsDisabled(consoleplayer) ) { kfail = true; diff --git a/zscript/handler/swwm_handler_damage.zsc b/zscript/handler/swwm_handler_damage.zsc index 062476f41..25cfb8d1e 100644 --- a/zscript/handler/swwm_handler_damage.zsc +++ b/zscript/handler/swwm_handler_damage.zsc @@ -128,7 +128,7 @@ extend Class SWWMHandler } // barrel destruction if ( (e.Thing is 'ExplosiveBarrel') && (e.Thing.Health <= 0) ) - SWWMUtility.AchievementProgressInc('swwm_progress_barrel',1,e.DamageSource.player); + SWWMUtility.AchievementProgressInc("barrel",1,e.DamageSource.player); } } @@ -189,34 +189,34 @@ extend Class SWWMHandler if ( e.Thing.IsHostile(src) ) { if ( e.Thing.bBOSS && ((e.DamageType == 'Dash') || (e.DamageType == 'Buttslam')) ) - SWWMUtility.AchievementProgressInc('swwm_progress_bossdash',1,src.player); + SWWMUtility.AchievementProgressInc("bossdash",1,src.player); if ( e.DamageType == 'Push' ) - SWWMUtility.AchievementProgressInc('swwm_progress_sneeze',1,src.player); + SWWMUtility.AchievementProgressInc("sneeze",1,src.player); else if ( e.DamageType == 'Buttslam' ) - SWWMUtility.AchievementProgressInc('swwm_progress_butts',1,src.player); + SWWMUtility.AchievementProgressInc("butts",1,src.player); else if ( e.DamageType == 'Jump' ) - SWWMUtility.AchievementProgressInc('swwm_progress_stomp',1,src.player); + SWWMUtility.AchievementProgressInc("stomp",1,src.player); else if ( e.DamageType == 'GroundPound' ) - SWWMUtility.AchievementProgressInc('swwm_progress_thicc',1,src.player); + SWWMUtility.AchievementProgressInc("thicc",1,src.player); else if ( (e.DamageType == 'Love') && !(e.Thing is 'WolfensteinSS') && (e.Thing.Species != 'WolfensteinSS') ) - SWWMUtility.AchievementProgressInc('swwm_progress_love',1,src.player); + SWWMUtility.AchievementProgressInc("love",1,src.player); Inventory buff = e.Inflictor?e.Inflictor.FindInventory('ParriedBuff'):null; if ( buff ) { - SWWMUtility.AchievementProgressInc('swwm_progress_reflect',1,src.player); + SWWMUtility.AchievementProgressInc("reflect",1,src.player); if ( (e.Thing is 'Cyberdemon') && (e.Inflictor is 'Rocket') && (buff.tracer == e.Thing) ) - SWWMUtility.MarkAchievement('swwm_achievement_cybully',src.player); + SWWMUtility.MarkAchievement("cybully",src.player); } if ( (e.Inflictor is 'PusherWeapon') || (e.Inflictor is 'PusherProjectile') ) - SWWMUtility.AchievementProgressInc('swwm_progress_tender',1,src.player); + SWWMUtility.AchievementProgressInc("tender",1,src.player); Inventory tk; if ( (tk = e.Thing.FindInventory("DeepImpactOnlyToken")) && (tk.special1 == 1) ) - SWWMUtility.MarkAchievement('swwm_achievement_shame',src.player); - SWWMUtility.AchievementProgressInc('swwm_progress_mega',1,src.player); + SWWMUtility.MarkAchievement("shame",src.player); + SWWMUtility.AchievementProgressInc("mega",1,src.player); if ( src.player.Health == 1 ) { onehpspree[pnum]++; - SWWMUtility.AchievementProgress('swwm_progress_onehp',onehpspree[pnum],src.player); + SWWMUtility.AchievementProgress("onehp",onehpspree[pnum],src.player); } } // no credits unless it's a counted kill or marine (that isn't friendly) or another player in DM @@ -306,7 +306,7 @@ extend Class SWWMHandler scr.xstr[ofs] = StringTable.Localize("$SWWM_OVERKILL"); scr.xcnt = ++ofs; } - SWWMUtility.AchievementProgressInc('swwm_progress_gib',1,src.player); + SWWMUtility.AchievementProgressInc("gib",1,src.player); } score = int(score*(1.+.5*min(multilevel[pnum],16))); if ( (multilevel[pnum] > 0) && scr ) @@ -352,7 +352,7 @@ extend Class SWWMHandler SWWMCredits.Give(src.player,1000); Console.Printf(StringTable.Localize("$SWWM_LASTMONSTER"),src.player.GetUserName(),1000); SWWMScoreObj.Spawn(1000,src.Vec3Offset(0,0,src.Height/2)); - SWWMUtility.AchievementProgressInc('swwm_progress_allkills',1,src.player); + SWWMUtility.AchievementProgressInc("allkills",1,src.player); } } diff --git a/zscript/handler/swwm_handler_replacements.zsc b/zscript/handler/swwm_handler_replacements.zsc index 91f5f9c10..26ef1f936 100644 --- a/zscript/handler/swwm_handler_replacements.zsc +++ b/zscript/handler/swwm_handler_replacements.zsc @@ -703,7 +703,7 @@ extend Class SWWMHandler || (e.Replacee is 'MWeaponPiece2') || (e.Replacee is 'MWeaponPiece3') ) e.Replacement = 'HammerspaceEmbiggener'; else if ( e.Replacee is 'ArmorBonus' ) e.Replacement = 'ArmorNuggetItem'; else if ( e.Replacee is 'HealthBonus' ) e.Replacement = 'HealthNuggetItem'; - else if ( (e.Replacee is 'ArtiTimeBomb') || (e.Replacee is 'ArtiBlastRadius') || (e.Replacee is 'ArtiPoisonBag') || (e.Replacee is 'ArtiHealingRadius') ) e.Replacement = (nugflip=!nugflip)?'HealthNugget':'ArmorNugget'; + else if ( (e.Replacee is 'ArtiTimeBomb') || (e.Replacee is 'ArtiBlastRadius') || (e.Replacee is 'ArtiPoisonBag') || (e.Replacee is 'ArtiHealingRadius') ) e.Replacement = (nugflip=!nugflip)?'HealthNuggetItem':'ArmorNuggetItem'; else if ( (e.Replacee is 'Stimpack') || (e.Replacee is 'CrystalVial') ) e.Replacement = 'TetraHealthItem'; else if ( (e.Replacee is 'Medikit') || (e.Replacee is 'ArtiHealth') ) e.Replacement = 'CubeHealthItem'; else if ( (e.Replacee is 'Soulsphere') || (e.Replacee is 'ArtiSuperHealth') ) e.Replacement = 'RefresherItem'; diff --git a/zscript/handler/swwm_handler_worldload.zsc b/zscript/handler/swwm_handler_worldload.zsc index edfa7b866..12ebfe993 100644 --- a/zscript/handler/swwm_handler_worldload.zsc +++ b/zscript/handler/swwm_handler_worldload.zsc @@ -93,7 +93,7 @@ extend Class SWWMHandler else if ( level.levelnum == 32 ) s.nazicleanup |= 2; } if ( s.nazicleanup == 3 ) - SWWMUtility.MarkAchievement('swwm_achievement_trash',s.myplayer); + SWWMUtility.MarkAchievement("trash",s.myplayer); } // reset score on dead players (death exit™) for ( int i=0; i 0) || (level.total_items > 0) || (level.total_secrets > 0)) && (level.killed_monsters == 0) && (level.found_items == 0) && (level.found_secrets == 0) ) - SWWMUtility.MarkAchievement('swwm_achievement_hurry',players[consoleplayer]); + SWWMUtility.MarkAchievement("hurry",players[consoleplayer]); } private void SetupLockdefsCache( SWWMCachedLockInfo cli ) diff --git a/zscript/handler/swwm_handler_worldtick.zsc b/zscript/handler/swwm_handler_worldtick.zsc index b78a3ab7f..f8c331636 100644 --- a/zscript/handler/swwm_handler_worldtick.zsc +++ b/zscript/handler/swwm_handler_worldtick.zsc @@ -56,7 +56,7 @@ extend Class SWWMHandler allitems = true; Console.Printf(StringTable.Localize("$SWWM_LASTITEM"),players[i].GetUserName(),500); score += 490; - SWWMUtility.AchievementProgressInc('swwm_progress_allitems',1,players[i]); + SWWMUtility.AchievementProgressInc("allitems",1,players[i]); } SWWMCredits.Give(players[i],score); SWWMScoreObj.Spawn(score,players[i].mo.Vec3Offset(0,0,players[i].mo.Height/2)); @@ -215,7 +215,7 @@ extend Class SWWMHandler if ( s.deaths > 0 ) return; } - SWWMUtility.MarkAchievement('swwm_achievement_wantdie',players[consoleplayer]); + SWWMUtility.MarkAchievement("wantdie",players[consoleplayer]); } // "simple" tracking (used by the minimap) diff --git a/zscript/handler/swwm_statichandler_achievements.zsc b/zscript/handler/swwm_statichandler_achievements.zsc index f0fc8d018..f9c0b4f52 100644 --- a/zscript/handler/swwm_statichandler_achievements.zsc +++ b/zscript/handler/swwm_statichandler_achievements.zsc @@ -1,32 +1,43 @@ // achievement tracking +Class SWWMAchievementInfo +{ + int baseindex; // sorting order in the list + String basename; // base name for identifying achievement + TextureID icon; // our icon + int maxval; // maximum value (0: no progress, -1: special scripting needed) + bool hasformat; // achievement description text must be formatted to add maxval + int state, val; // set by other scripts, used to avoid excessive dictionary lookups +} + extend Class SWWMStaticHandler { ui int lastachievementnotify; // prevent overlap - Array achievements; + Dictionary achievementstate, achievementprogress; + Array achievementinfo; // specific info on achievements - private ui bool CheckAchievement( SWWMAchievement a ) + private ui bool CheckAchievement( SWWMAchievementInfo a ) { - int val = a.state.GetInt(); + int val = achievementstate.At(a.basename).ToInt(); // manually check progress - if ( a.progress ) + if ( a.maxval ) { - int prog = a.progress.GetInt(); + int prog = achievementprogress.At(a.basename).ToInt(); // special cases if ( val && (prog < a.maxval) ) { - a.state.SetInt(0); + achievementstate.Insert(a.basename,"0"); val = 0; } else if ( !val && (prog >= a.maxval) ) { - a.state.SetInt(1); + achievementstate.Insert(a.basename,"1"); val = 1; } } if ( (val == 1) && (gametic > lastachievementnotify) ) { - a.state.SetInt(2); + achievementstate.Insert(a.basename,"2"); EventHandler.SendNetworkEvent("swwmachievement."..a.basename,consoleplayer); let notif = new("SWWMAchievementNotification").Init(a.basename,a.icon,a.hasformat?a.maxval:0); StatusBar.AttachMessage(notif,-3478); @@ -39,38 +50,267 @@ extend Class SWWMStaticHandler { // don't check constantly, and don't check during level transitions if ( unloading || (maptime < 105) || (maptime%35) ) return; - // first load - if ( achievements.Size() <= 0 ) SWWMUtility.LoadAchievements(achievements); bool alldone = true; int ev = -1; - for ( int i=0; i lastachievementnotify) ) { - achievements[ev].state.SetInt(2); - EventHandler.SendNetworkEvent("swwmachievement."..achievements[ev].basename,consoleplayer); - let notif = new("SWWMAchievementNotification").Init(achievements[ev].basename,achievements[ev].icon); + achievementstate.Insert("everything","2"); + EventHandler.SendNetworkEvent("swwmachievement."..achievementinfo[ev].basename,consoleplayer); + let notif = new("SWWMAchievementNotification").Init(achievementinfo[ev].basename,achievementinfo[ev].icon); StatusBar.AttachMessage(notif,-3478); lastachievementnotify = gametic+200; } } + + // parses achievements.lst file(s) + private void ParseAchievementList( out Array achievements ) + { + achievements.Clear(); + let lmp = Wads.FindLump("achievements.lst"); + if ( lmp == -1 ) ThrowAbortException("'achievements.lst' not found"); + String dat; + Array list, ln; + int bidx = 0; + while ( lmp != -1 ) + { + dat = Wads.ReadLump(lmp); + // fucking Windows + dat.Replace("\r",""); + list.Clear(); + dat.Split(list,"\n"); + for ( int i=0; i)(AllActorClasses[i]); + if ( !c || (c == 'SWWMCollectible') ) continue; + let def = GetDefaultByType(c); + // check that we can collect it in this IWAD + if ( !def.ValidGame() ) continue; + nc++; + } + ac.maxval = nc; + } + ac.hasformat = (ln[2]~=="yes"); + achievements.Push(ac); + bidx++; + } + lmp = Wads.FindLump("achievements.lst",lmp+1); + } + } + + // load all achievement state and progress + private void LoadAchievements() + { + String statestr = swwm_achievementstate; + String progstr = swwm_achievementprogress; + // invalid length? + if ( (statestr.length()%2) || (progstr.length()%2) ) + { + CreateAchievements(); + return; + } + // decode + int cypher[] = {0xAD,0xEA,0xDB,0xED}; + String nstr = ""; + for ( int i=0; i keys; + keys.Clear(); + statestr.Split(keys,","); + for ( int i=0; i>4)+0x41; + nstr.AppendFormat("%c%c",b,c); + } + statestr = nstr; + nstr = ""; + for ( int i=0; i>4)+0x41; + nstr.AppendFormat("%c%c",b,c); + } + progstr = nstr; + let cv = CVar.FindCVar('swwm_achievementstate'); + cv.SetString(statestr); + cv = CVar.FindCVar('swwm_achievementprogress'); + cv.SetString(progstr); + } + + // blank achievement creation, used if loading fails + private void CreateAchievements() + { + achievementstate = Dictionary.Create(); + achievementprogress = Dictionary.Create(); + ParseAchievementList(achievementinfo); + for ( int i=0; i= tpuz ) SWWMUtility.MarkAchievement('swwm_achievement_puzzle',players[consoleplayer]); + if ( realpuzzlecnt >= tpuz ) SWWMUtility.MarkAchievement("puzzle",players[consoleplayer]); if ( !swwm_nomapmsg ) { switch ( puzzlecnt ) diff --git a/zscript/items/swwm_ammoitems.zsc b/zscript/items/swwm_ammoitems.zsc index 735b403f8..cca3cd557 100644 --- a/zscript/items/swwm_ammoitems.zsc +++ b/zscript/items/swwm_ammoitems.zsc @@ -381,6 +381,7 @@ Class GoldShell : SWWMAmmo //$Icon ammo Tag "$T_GOLDSHELL"; SWWMAmmo.PickupTag "GOLDSHELL"; + Inventory.PickupSound "misc/ammo_pkup_vip"; Stamina -1000000; Inventory.Icon "graphics/HUD/Icons/A_ShellsGold.png"; Inventory.Amount 1; diff --git a/zscript/items/swwm_armor.zsc b/zscript/items/swwm_armor.zsc index 0bffc56ba..4f9139738 100644 --- a/zscript/items/swwm_armor.zsc +++ b/zscript/items/swwm_armor.zsc @@ -29,7 +29,7 @@ Class ArmorNuggetItem : SWWMSpareArmor override void DoPickupSpecial( Actor toucher ) { Super.DoPickupSpecial(toucher); - SWWMUtility.AchievementProgressInc('swwm_progress_candy',1,toucher.player); + SWWMUtility.AchievementProgressInc("candy",1,toucher.player); } Default diff --git a/zscript/items/swwm_collectibles.zsc b/zscript/items/swwm_collectibles.zsc index 57dc57e00..50af470c1 100644 --- a/zscript/items/swwm_collectibles.zsc +++ b/zscript/items/swwm_collectibles.zsc @@ -86,7 +86,7 @@ Class SWWMCollectible : Inventory abstract if ( !(i is 'SWWMCollectible') ) continue; cnc++; } - SWWMUtility.AchievementProgress('swwm_progress_allcoll',cnc,other.player); + SWWMUtility.AchievementProgress("allcoll",cnc,other.player); // we're only attaching to the other players if ( propagated ) return; // give credit diff --git a/zscript/items/swwm_health.zsc b/zscript/items/swwm_health.zsc index 60d01dcb4..30940f31f 100644 --- a/zscript/items/swwm_health.zsc +++ b/zscript/items/swwm_health.zsc @@ -74,7 +74,7 @@ Class HealthNuggetItem : SWWMHealth override void DoPickupSpecial( Actor toucher ) { Super.DoPickupSpecial(toucher); - SWWMUtility.AchievementProgressInc('swwm_progress_candy',1,toucher.player); + SWWMUtility.AchievementProgressInc("candy",1,toucher.player); } Default { @@ -179,7 +179,7 @@ Class RefresherItem : SWWMHealth } override void AutoUseExtra( bool recursive ) { - SWWMUtility.AchievementProgressInc('swwm_progress_refresh',1,Owner.player); + SWWMUtility.AchievementProgressInc("refresh",1,Owner.player); // regen effect doesn't stack if we autoactivated recursively if ( recursive ) return; let p = Powerup(Owner.FindInventory("RefresherRegen")); diff --git a/zscript/items/swwm_powerups.zsc b/zscript/items/swwm_powerups.zsc index 92813af2a..2360fb0f0 100644 --- a/zscript/items/swwm_powerups.zsc +++ b/zscript/items/swwm_powerups.zsc @@ -38,7 +38,7 @@ Class GrilledCheeseSandwich : Inventory } void DoTheThing( bool extrasafe = false ) { - SWWMUtility.AchievementProgressInc('swwm_progress_gcsandwich',1,Owner.player); + SWWMUtility.AchievementProgressInc("gcsandwich",1,Owner.player); SWWMHandler.DoFlash(Owner,Color(64,255,255,64),10); Owner.A_QuakeEx(9,9,9,3,0,1,"",QF_RELATIVE|QF_SCALEDOWN,rollIntensity:1.); Owner.GiveBody(1000,1000); @@ -204,7 +204,7 @@ Class GrilledCheeseSandwich : Inventory override void PostTeleport( Vector3 destpos, double destangle, int flags ) { if ( !lastdropper ) return; - SWWMUtility.MarkAchievement('swwm_achievement_tele',lastdropper.player); + SWWMUtility.MarkAchievement("tele",lastdropper.player); } Default @@ -504,7 +504,7 @@ Class GhostArtifact : Inventory Demolitionist(Owner).lastbump *= 1.04; } else Owner.GiveInventory("GhostPower",1); - SWWMUtility.AchievementProgressInc('swwm_progress_ghost',1,Owner.player); + SWWMUtility.AchievementProgressInc("ghost",1,Owner.player); return true; } @@ -658,7 +658,7 @@ Class GravitySuppressor : Inventory Demolitionist(Owner).lastbump *= 1.04; } else Owner.GiveInventory("GravityPower",1); - SWWMUtility.AchievementProgressInc('swwm_progress_gravity',1,Owner.player); + SWWMUtility.AchievementProgressInc("gravity",1,Owner.player); return true; } override void Travelled() @@ -908,7 +908,7 @@ Class FuckingInvinciball : Inventory Demolitionist(Owner).lastbump *= 1.1; } else Owner.GiveInventory("InvinciballPower",1); - SWWMUtility.AchievementProgressInc('swwm_progress_sunny',1,Owner.player); + SWWMUtility.AchievementProgressInc("sunny",1,Owner.player); return true; } override void Travelled() @@ -1183,7 +1183,7 @@ Class Ragekit : Inventory if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA); if ( Owner.GiveBody(100,100) ) SWWMScoreObj.Spawn(100,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health); - SWWMUtility.AchievementProgressInc('swwm_progress_rage',1,Owner.player); + SWWMUtility.AchievementProgressInc("rage",1,Owner.player); if ( !(Owner is 'Demolitionist') ) { SWWMHandler.DoFlash(Owner,Color(64,255,0,0),30); @@ -1711,7 +1711,7 @@ Class CompanionLamp : Actor m.lamp = self; m.trail = m.pos; moff.Push(m); - SWWMUtility.AchievementProgressInc('swwm_progress_moth',1,parent.player); + SWWMUtility.AchievementProgressInc("moth",1,parent.player); } override void PostBeginPlay() { @@ -2184,7 +2184,7 @@ Class EBarrier : Inventory Demolitionist(Owner).lastbump *= 0.95; } else Owner.GiveInventory("BarrierPower",1); - SWWMUtility.AchievementProgressInc('swwm_progress_barrier',1,Owner.player); + SWWMUtility.AchievementProgressInc("barrier",1,Owner.player); return true; } override void Travelled() @@ -2851,14 +2851,14 @@ Class Mykradvo : Inventory return true; } if ( (targets.Size() == 1) && targets[0] && !targets[0].bBOSS ) - SWWMUtility.MarkAchievement('swwm_achievement_anone',Owner.player); + SWWMUtility.MarkAchievement("anone",Owner.player); let p = Spawn("MykradvoBurst",spawnpos); p.target = Owner; MykradvoBurst(p).targets.Move(targets); targets.Clear(); if ( Owner is 'Demolitionist' ) Demolitionist(Owner).lastbump *= 1.2; - SWWMUtility.AchievementProgressInc('swwm_progress_anom',1,Owner.player); + SWWMUtility.AchievementProgressInc("anom",1,Owner.player); return true; } @@ -3111,7 +3111,7 @@ Class SafetyTether : Inventory SWWMHandler.DoFlash(Owner,Color(255,128,192,255),30); if ( Owner.GiveBody(100,100) ) SWWMScoreObj.Spawn(100,Owner.Vec3Offset(FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8),FRandom[ScoreBits](-8,8)+Owner.Height/2),ST_Health); - SWWMUtility.AchievementProgressInc('swwm_progress_sneaky',1,Owner.player); + SWWMUtility.AchievementProgressInc("sneaky",1,Owner.player); Amount--; if ( Amount <= 0 ) DepleteOrDestroy(); } @@ -3316,7 +3316,7 @@ Class AngerySigil : Inventory { if ( pickup && !deathmatch ) return false; if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA,CHANF_OVERLAP); - SWWMUtility.AchievementProgressInc('swwm_progress_deva',1,Owner.player); + SWWMUtility.AchievementProgressInc("deva",1,Owner.player); let r = AngeryPower(Owner.FindInventory("AngeryPower")); if ( r ) { @@ -3593,7 +3593,7 @@ Class DivineSprite : Inventory if ( p ) return false; 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); + SWWMUtility.AchievementProgressInc("divine",1,Owner.player); return true; } override void Travelled() diff --git a/zscript/kbase/swwm_kbase.zsc b/zscript/kbase/swwm_kbase.zsc index 12b1118a6..477b30f81 100644 --- a/zscript/kbase/swwm_kbase.zsc +++ b/zscript/kbase/swwm_kbase.zsc @@ -16,11 +16,15 @@ Class MenuTransaction Class DemolitionistMenu : GenericMenu { transient Font TewiFont, MPlusFont, MiniwiFont, k6x8Font; + TextureID FancyBg, FrameTex, VSepTex, HSepTex; + // for resolution scaling and such + double hs; + Vector2 ss, ws, origin; // temporary bottom messages, such as "not enough money" String tmsg; int tmsgtic; - // bottom clock - String clockstr; + // other text + String clockstr, munstr; // menu keybind int ikey[2]; String mkey[2]; @@ -59,7 +63,19 @@ Class DemolitionistMenu : GenericMenu isclosing = true; return; } - // TODO initialize base graphics here + FancyBg = TexMan.CheckForTexture("graphics/tempbg.png",TexMan.Type_MiscPatch); + FrameTex = TexMan.CheckForTexture("graphics/KBase/FrameTex.png",TexMan.Type_MiscPatch); + VSepTex = TexMan.CheckForTexture("graphics/KBase/VSepTex.png",TexMan.Type_MiscPatch); + HSepTex = TexMan.CheckForTexture("graphics/KBase/HSepTex.png",TexMan.Type_MiscPatch); + // note that we can assume 640x400 will always be the smallest resolution allowed by gzdoom, but we still need to handle widescreen + hs = max(min(floor(Screen.GetWidth()/640.),floor(Screen.GetHeight()/266.)),1.); + ss = (Screen.GetWidth(),Screen.GetHeight())/hs; + ws.x = 640.; + double th = 640*(ss.y/ss.x); + if ( th >= 400. ) ws.y = 400.; + else if ( th >= 360. ) ws.y = 360.; + else ws.y = 266.; + origin = (int(ss.x-ws.x)/2,int(ss.y-ws.y)/2); TewiFont = Font.GetFont('TewiShaded'); MPlusFont = Font.GetFont('MPlusShaded'); MiniwiFont = Font.GetFont('MiniwiShaded'); @@ -69,7 +85,7 @@ Class DemolitionistMenu : GenericMenu mkey[0] = Bindings.NameKeys(ikey[0],0); mkey[1] = Bindings.NameKeys(ikey[1],0); tmsg = StringTable.Localize("$SWWM_MAINCONTROLS"); - tmsgtic = gametic+70; + tmsgtic = gametic+50; lasttuid = Random[TUID](); hnd = SWWMHandler(EventHandler.Find("SWWMHandler")); SetClock(); @@ -81,6 +97,7 @@ Class DemolitionistMenu : GenericMenu switch ( mkey ) { case MKEY_BACK: + isclosing = true; MenuSound("menu/democlose"); EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer); Close(); @@ -95,6 +112,7 @@ Class DemolitionistMenu : GenericMenu if ( (gamestate != GS_LEVEL) || (players[consoleplayer].Health <= 0) || isclosing ) { // ded (or force close) + isclosing = true; EventHandler.SendNetworkEvent("swwmclearalltransactions",consoleplayer); Close(); return; @@ -107,6 +125,12 @@ Class DemolitionistMenu : GenericMenu CheckTransactions(); // update time string clockstr = CrimeTime(); + // update money str + int muns1, muns2; + [muns1, muns2] = SWWMCredits.Get(players[consoleplayer]); + munstr = "\cg¥\c-"; + if ( muns2 > 0 ) munstr.AppendFormat("%d",muns2); + munstr.AppendFormat("%09d",muns1); } override bool OnUiEvent( UIEvent ev ) @@ -126,11 +150,72 @@ Class DemolitionistMenu : GenericMenu return Super.OnUiEvent(ev); } + // fundamental drawing functions (good god these are hacky) + void DrawFrame( double x, double y, double w, double h, bool shadow = true ) + { + x += origin.x; + y += origin.y; + Screen.DrawTexture(FrameTex,false,x,y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,0.,DTA_SrcY,0.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,1); + Screen.DrawTexture(FrameTex,false,x+1,y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,1.,DTA_SrcY,0.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,int(w-2),DTA_DestHeight,1); + Screen.DrawTexture(FrameTex,false,x,y+1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,0.,DTA_SrcY,1.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,int(h-2)); + Screen.DrawTexture(FrameTex,false,(x+w)-1,y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcY,0.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,1); + Screen.DrawTexture(FrameTex,false,x,(y+h)-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,0.,DTA_SrcY,2.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,1); + if ( shadow ) + { + Screen.DrawTexture(FrameTex,false,(x+w)-1,y+1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcY,1.,DTA_SrcWidth,2.,DTA_SrcHeight,1.,DTA_DestWidth,2,DTA_DestHeight,int(h-2)); + Screen.DrawTexture(FrameTex,false,x+1,(y+h)-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,1.,DTA_SrcY,2.,DTA_SrcWidth,1.,DTA_SrcHeight,2.,DTA_DestWidth,int(w-2),DTA_DestHeight,2); + Screen.DrawTexture(FrameTex,false,(x+w)-1,(y+h)-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcY,2.,DTA_SrcWidth,2.,DTA_SrcHeight,2.,DTA_DestWidth,2,DTA_DestHeight,2); + } + else + { + Screen.DrawTexture(FrameTex,false,(x+w)-1,y+1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcY,1.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,int(h-2)); + Screen.DrawTexture(FrameTex,false,x+1,(y+h)-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,1.,DTA_SrcY,2.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,int(w-2),DTA_DestHeight,1); + Screen.DrawTexture(FrameTex,false,(x+w)-1,(y+h)-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcY,2.,DTA_SrcWidth,1.,DTA_SrcHeight,1.,DTA_DestWidth,1,DTA_DestHeight,1); + } + } + + // these ones thankfully only need three drawtexture calls each + void DrawVSeparator( double x, double y, double h ) + { + x += origin.x; + y += origin.y; + } + void DrawHSeparator( double x, double y, double w ) + { + x += origin.x; + y += origin.y; + Screen.DrawTexture(HSepTex,false,x,y-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,0.,DTA_SrcWidth,1.,DTA_DestWidth,1); + Screen.DrawTexture(HSepTex,false,x+1,y-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,1.,DTA_SrcWidth,1.,DTA_DestWidth,int(ws.x-2)); + Screen.DrawTexture(HSepTex,false,(x+w)-1,y-1,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_SrcX,2.,DTA_SrcWidth,1.,DTA_DestWidth,1); + } + override void Drawer() { if ( isclosing ) return; + // draw the background and main frame + if ( swwm_fuzz ) Screen.DrawTexture(FancyBg,false,origin.x,origin.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_LegacyRenderStyle,STYLE_Add,DTA_Alpha,.5,DTA_ClipBottom,int((origin.y+ws.y)*hs)); + Screen.Dim("Black",.8,int(origin.x*hs),int(origin.y*hs),int(ws.x*hs),int(ws.y*hs)); + DrawFrame(0,0,ws.x,ws.y,true); + // draw top and bottom separators + DrawHSeparator(0,14,ws.x); + DrawHSeparator(0,ws.y-14,ws.x); Font fnt = LangFont(TewiFont); - String str = "NEW DEMOLITIONIST MENU IS UNDER CONSTRUCTION"; - Screen.DrawText(fnt,Font.CR_RED,(Screen.GetWidth()-fnt.StringWidth(str)*CleanXFac_1)/2,(Screen.GetHeight()-fnt.GetHeight()*CleanYFac_1)/2,str,DTA_CleanNoMove_1,true); + double xx = 3, yy = 0; + String str; + // TODO draw tabs + // ...and everything else + xx = 637-TewiFont.StringWidth(munstr); + Screen.DrawText(TewiFont,Font.CR_FIRE,origin.x+xx,origin.y+yy,munstr,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); + yy = ws.y-14; + if ( gametic < tmsgtic ) str = tmsg; + else str = clockstr; + xx = 4; + Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); + str = "DemolitionOS v1.0"; + xx = 637-fnt.StringWidth(str); + Screen.DrawText(fnt,Font.CR_WHITE,origin.x+xx,origin.y+yy,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); + // placeholder + str = "NEW DEMOLITIONIST MENU IS UNDER CONSTRUCTION"; + Screen.DrawText(fnt,Font.CR_RED,int(ss.x-fnt.StringWidth(str))/2,int(ss.y-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true); } } diff --git a/zscript/menu/swwm_achievementmenu.zsc b/zscript/menu/swwm_achievementmenu.zsc index 2e0ee1b50..d84977447 100644 --- a/zscript/menu/swwm_achievementmenu.zsc +++ b/zscript/menu/swwm_achievementmenu.zsc @@ -6,7 +6,8 @@ Class SWWMAchievementMenu : GenericMenu // so put everything in here TextureID AchievementUnknown, SelectBox, BaseBox; bool ShouldObscure; - Array mItems; + SWWMStaticHandler hnd; + Array mItems; String mTitle; int mSelected; int mBaseY; // Y position achievement boxes are being drawn at @@ -18,9 +19,31 @@ Class SWWMAchievementMenu : GenericMenu Super.Init(parent); mTitle = StringTable.Localize("$SWWM_ATITLE"); mSelected = 0; - SWWMUtility.LoadAchievements(mItems,false); // gotta load it unfiltered first + hnd = SWWMStaticHandler(StaticEventHandler.Find("SWWMStaticHandler")); + if ( !hnd ) ThrowAbortException("SWWMStaticHandler not found???"); + mItems.Copy(hnd.achievementinfo); total = mItems.Size(); - SWWMUtility.LoadAchievements(mItems,true); + bool dohide = (swwm_filterachievements==2); + for ( int i=0; i= left) && (mx < right) && (my >= top) && (my < bottom) ) { - int left = xx+4*CleanXFac_1; - int top = yy+4*CleanXFac_1; - int right = left+32*CleanXFac_1; - int bottom = top+32*CleanXFac_1; - if ( (mx >= left) && (mx < right) && (my >= top) && (my < bottom) ) - { - if ( i != mSelected ) MenuSound("menu/cursor"); - mSelected = i; - return res; - } - xx += 40*CleanXFac_1; - if ( !((i+1)%12) ) - { - xx = (Screen.GetWidth()-480*CleanXFac_1)/2; - yy += 40*CleanYFac_1; - } + if ( i != mSelected ) MenuSound("menu/cursor"); + mSelected = i; + return res; + } + xx += 40*CleanXFac_1; + if ( !((i+1)%12) ) + { + xx = (Screen.GetWidth()-480*CleanXFac_1)/2; + yy += 40*CleanYFac_1; } } return res; @@ -185,12 +205,11 @@ Class SWWMAchievementMenu : GenericMenu for ( i=0; i mystats.topspeed ) mystats.topspeed = vel.length(); if ( vel.length() > ((3600*GameTicRate)/32000.) ) - SWWMUtility.AchievementProgress('swwm_progress_sanic',int((vel.length()*3600*GameTicRate)/32000.),player); + SWWMUtility.AchievementProgress("sanic",int((vel.length()*3600*GameTicRate)/32000.),player); if ( !myvoice ) myvoice = CVar.GetCVar('swwm_voicetype',player); if ( player.onground && !bNoGravity && !lastground && (waterlevel < 2) ) { @@ -1120,7 +1120,7 @@ Class Demolitionist : PlayerPawn } encroachtics++; if ( !(encroachtics%GameTicRate) && !IsFriend(encroached) ) - SWWMUtility.AchievementProgress('swwm_progress_step',encroachtics/GameTicRate,player); + SWWMUtility.AchievementProgress("step",encroachtics/GameTicRate,player); } else encroachtics = 0; oldencroached = encroached; @@ -1259,7 +1259,7 @@ Class Demolitionist : PlayerPawn { if ( bumped ) continue; bumped = true; - SWWMUtility.AchievementProgressInc('swwm_progress_bonk',1,player); + SWWMUtility.AchievementProgressInc("bonk",1,player); A_QuakeEx(8,8,8,16,0,128,"",QF_RELATIVE|QF_SCALEDOWN); vel *= .2; vel -= dir*(10+(spd*30/mass)); @@ -1373,7 +1373,7 @@ Class Demolitionist : PlayerPawn { // headbump bumped = true; - SWWMUtility.AchievementProgressInc('swwm_progress_bonk',1,player); + SWWMUtility.AchievementProgressInc("bonk",1,player); A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP); bumptic = gametic+int(20+spd/4.); lastbump *= .8; @@ -1470,7 +1470,7 @@ Class Demolitionist : PlayerPawn } // wallbump bumped = true; - SWWMUtility.AchievementProgressInc('swwm_progress_bonk',1,player); + SWWMUtility.AchievementProgressInc("bonk",1,player); A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP); bumptic = gametic+int(25+spd/4.); lastbump *= .8; @@ -1572,7 +1572,7 @@ Class Demolitionist : PlayerPawn q.special1 = 10; SWWMCrusherBroken.Create(flor,null,diffh); } - SWWMUtility.MarkAchievement('swwm_achievement_crush',player); + SWWMUtility.MarkAchievement("crush",player); } override int DamageMobj( Actor inflictor, Actor source, int damage, Name mod, int flags, double angle ) { @@ -1614,7 +1614,7 @@ Class Demolitionist : PlayerPawn if ( source.master ) source.master.Destroy(); source.Destroy(); damage = 20; // reduce so it's not instant kill - SWWMUtility.MarkAchievement('swwm_achievement_kancho',player); + SWWMUtility.MarkAchievement("kancho",player); } } // no damage whatsoever @@ -1642,7 +1642,7 @@ Class Demolitionist : PlayerPawn } PainChance = oldpchance; if ( (Health <= 0) && (source == self) && (flags&DMG_EXPLOSION) ) - SWWMUtility.MarkAchievement('swwm_achievement_dime',player); + SWWMUtility.MarkAchievement("dime",player); return realdmg; } override void CalcHeight() @@ -2051,7 +2051,7 @@ Class Demolitionist : PlayerPawn A_StartSound(walljump?"demolitionist/kick":"demolitionist/runstart",CHAN_FOOTSTEP,CHANF_OVERLAP); if ( swwm_extraalert ) A_AlertMonsters(swwm_uncapalert?0:100); last_kick = level.maptime+1; - SWWMUtility.AchievementProgressInc('swwm_progress_jump',1,player); + SWWMUtility.AchievementProgressInc("jump",1,player); } } bOnMobj = false; @@ -2088,7 +2088,7 @@ Class Demolitionist : PlayerPawn { if ( !bWalking && (level.maptime < (lastairtic+10)) ) { - SWWMUtility.AchievementProgressInc('swwm_progress_bune',1,player); + SWWMUtility.AchievementProgressInc("bune",1,player); // bhop, z vel relative to vel size if ( vel.z < 25. ) // don't ramp up too hard { @@ -2170,7 +2170,7 @@ Class Demolitionist : PlayerPawn // reboot (if possible) if ( !FindInventory("ReviveCooldown") && (((swwm_revivecooldown >= 0) && (G_SkillPropertyInt(SKILLP_ACSReturn) < 4)) || !hasrevived) ) { - if ( hasrevived ) SWWMUtility.MarkAchievement('swwm_achievement_sekiro',player); + if ( hasrevived ) SWWMUtility.MarkAchievement("sekiro",player); hasrevived = true; player.Resurrect(); player.damagecount = 0; @@ -2647,7 +2647,7 @@ Class Demolitionist : PlayerPawn if ( hnd ) hnd.allsecrets = true; score = 1000; Console.Printf(StringTable.Localize("$SWWM_LASTSECRET"),player.GetUserName(),score); - SWWMUtility.AchievementProgressInc('swwm_progress_allsecrets',1,player); + SWWMUtility.AchievementProgressInc("allsecrets",1,player); } else Console.Printf(StringTable.Localize("$SWWM_FINDSECRET"),player.GetUserName(),score); if ( CheckLocalView() ) SWWMHandler.AddOneliner("findsecret",2,40); diff --git a/zscript/swwm_statichandler.zsc b/zscript/swwm_statichandler.zsc index 27cafd18c..dd7e53dee 100644 --- a/zscript/swwm_statichandler.zsc +++ b/zscript/swwm_statichandler.zsc @@ -54,22 +54,6 @@ Class SWWMStaticHandler : StaticEventHandler Demolitionist(players[i].mo).CheckUnderwaterAmb(true); } } - if ( players[consoleplayer].mo ) - { - // recheck progress on some per-session achievements - if ( swwm_achievement_allcoll <= 0 ) - { - int nc = 0; - for ( Inventory i=players[consoleplayer].mo.inv; i; i=i.inv ) if ( i is 'SWWMCollectible' ) nc++; - CVar.FindCVar('swwm_progress_allcoll').SetInt(nc); - } - if ( swwm_achievement_plush <= 0 ) - { - let s = SWWMStats.Find(players[consoleplayer]); - if ( s ) CVar.FindCVar('swwm_progress_plush').SetInt(s.plushuses); - else CVar.FindCVar('swwm_progress_plush').SetInt(0); - } - } SWWMHandler.ClearAllShaders(players[consoleplayer]); // force a reset of the minimap zoom in case it's set beyond safe levels double mmz = swwm_mm_zoom; @@ -96,6 +80,12 @@ Class SWWMStaticHandler : StaticEventHandler } } + override void OnUnregister() + { + // save achievements on exit + SaveAchievements(); + } + override void OnRegister() { // preload various fonts @@ -124,6 +114,9 @@ Class SWWMStaticHandler : StaticEventHandler let cv = CVar.FindCVar('swwm_voicetype'); if ( types.Find(cv.GetString()) >= types.Size() ) cv.SetString("default"); + // load up the achievements + if ( swwm_achievementstate == "" ) MigrateAchievements(); + else LoadAchievements(); // warning for unsupported if ( Wads.FindLump("swwmgamesupported.txt") != -1 ) return; Console.Printf( @@ -160,8 +153,8 @@ Class SWWMStaticHandler : StaticEventHandler { // don't reset these if ( (cvarlist[i] == "swwm_playtime") - || (cvarlist[i].Left(17) == "swwm_achievement_") - || (cvarlist[i].Left(14) == "swwm_progress_") ) + || (cvarlist[i] == "swwm_achievementstate") + || (cvarlist[i] == "swwm_achievementprogress") ) continue; CVar.FindCVar(cvarlist[i]).ResetToDefault(); } @@ -211,26 +204,23 @@ Class SWWMStaticHandler : StaticEventHandler } else if ( e.Name ~== "swwmresetachievements" ) { - if ( achievements.Size() <= 0 ) - SWWMUtility.LoadAchievements(achievements); - for ( int i=0; i 0) || (curamt+amount < curamt) || (curamt+amount >= 1000000000) ) - SWWMUtility.AchievementProgress('swwm_progress_dosh',1000000000,p); - else SWWMUtility.AchievementProgress('swwm_progress_dosh',curamt+amount,p); + SWWMUtility.AchievementProgress("dosh",1000000000,p); + else SWWMUtility.AchievementProgress("dosh",curamt+amount,p); } static clearscope bool CanTake( PlayerInfo p, int amount, int hamount = 0 ) diff --git a/zscript/utility/swwm_utility.zsc b/zscript/utility/swwm_utility.zsc index 917562fc9..45e8b4065 100644 --- a/zscript/utility/swwm_utility.zsc +++ b/zscript/utility/swwm_utility.zsc @@ -13,16 +13,6 @@ enum EDoExplosionFlags DE_COUNTSTEALTH = 256, // only count hits for inactive monsters }; -Class SWWMAchievement -{ - int baseindex; // order of the achievement in the list - String basename; - transient CVar state, progress; - TextureID icon; - int maxval; - bool hasformat; -} - Struct SWWMProjectionData { swwm_GM_Matrix wtc; @@ -31,134 +21,73 @@ Struct SWWMProjectionData Class SWWMUtility { - // loaded from a file, neater than having a bunch of static arrays - // filter: excludes unobtained achievements if swwm_filterachievements is 2 - // also excludes the "everything" achievement unless unlocked - static clearscope void LoadAchievements( out Array achievements, bool filter = false ) - { - achievements.Clear(); - let lmp = Wads.FindLump("achievements.lst"); - if ( lmp == -1 ) ThrowAbortException("'achievements.lst' not found"); - String dat; - Array list, ln; - bool hide = (filter&&(swwm_filterachievements==2)); - int bidx = 0; - while ( lmp != -1 ) - { - dat = Wads.ReadLump(lmp); - // fucking Windows - dat.Replace("\r",""); - list.Clear(); - dat.Split(list,"\n"); - for ( int i=0; i)(AllActorClasses[i]); - if ( !c || (c == 'SWWMCollectible') ) continue; - let def = GetDefaultByType(c); - // check that we can collect it in this IWAD - if ( !def.ValidGame() ) continue; - nc++; - } - ac.maxval = nc; - } - } - else ac.progress = null; - // hide away achievements at 0% - if ( hide && (ac.state.GetInt() <= 0) && (!ac.progress || (ac.progress.GetInt() <= 0)) ) - { - ac.Destroy(); - continue; - } - ac.hasformat = (ln[2]~=="yes"); - ac.icon = TexMan.CheckForTexture("graphics/Achievements/Achievement"..ac.basename..".png",TexMan.Type_Any); - // fallback icon if one is not found - if ( !ac.icon.IsValid() ) ac.icon = TexMan.CheckForTexture("graphics/Achievements/DefaultAchievement.png",TexMan.Type_Any); - achievements.Push(ac); - bidx++; - } - lmp = Wads.FindLump("achievements.lst",lmp+1); - } - } // achievement helpers - static clearscope void MarkAchievement( Name mvar, PlayerInfo p = null ) + static clearscope void MarkAchievement( String mvar, PlayerInfo p = null ) { if ( !p || (p != players[consoleplayer]) ) return; - let cv = CVar.FindCVar(mvar); - if ( !cv ) + let hnd = SWWMStaticHandler(StaticEventHandler.Find("SWWMStaticHandler")); + if ( !hnd ) return; + String val = hnd.achievementstate.At(mvar); + if ( val == "" ) { - if ( developer >= 2 ) Console.Printf("MarkAchievement: CVar '"..mvar.."' not found"); + if ( developer >= 2 ) Console.Printf("MarkAchievement: achievement '"..mvar.."' not found"); return; } - if ( cv.GetInt() < 1 ) cv.SetInt(1); + if ( val == "2" ) return; + hnd.achievementstate.Insert(mvar,"1"); } - static clearscope void AchievementProgress( Name pvar, int val, PlayerInfo p = null ) + static clearscope int GetAchievementProgress( String pvar, PlayerInfo p = null ) { - if ( !p || (p != players[consoleplayer]) ) return; - let cv = CVar.FindCVar(pvar); - if ( !cv ) + if ( !p || (p != players[consoleplayer]) ) return 0; + let hnd = SWWMStaticHandler(StaticEventHandler.Find("SWWMStaticHandler")); + if ( !hnd ) return 0; + String pval = hnd.achievementprogress.At(pvar); + if ( pval == "" ) { - if ( developer >= 2 ) Console.Printf("AchievementProgress: CVar '"..pvar.."' not found"); - return; + if ( developer >= 2 ) Console.Printf("AchievementProgress: achievement '"..pvar.."' not found"); + return 0; } - int cval = cv.GetInt(); - if ( val <= cval ) return; - cv.SetInt(val); + return pval.ToInt(); } - static clearscope void AchievementProgressInc( Name pvar, int inc, PlayerInfo p = null ) + static clearscope void AchievementProgress( String pvar, int val, PlayerInfo p = null ) { if ( !p || (p != players[consoleplayer]) ) return; - let cv = CVar.FindCVar(pvar); - if ( !cv ) + let hnd = SWWMStaticHandler(StaticEventHandler.Find("SWWMStaticHandler")); + if ( !hnd ) return; + String pval = hnd.achievementprogress.At(pvar); + if ( pval == "" ) { - if ( developer >= 2 ) Console.Printf("AchievementProgressInc: CVar '"..pvar.."' not found"); + if ( developer >= 2 ) Console.Printf("AchievementProgress: achievement '"..pvar.."' not found"); return; } - int cval = cv.GetInt(); - cv.SetInt(cval+inc); + if ( val <= pval.ToInt() ) return; + hnd.achievementprogress.Insert(pvar,String.Format("%d",val)); } - static clearscope void AchievementProgressIncDouble( Name pvar, double inc, PlayerInfo p = null ) + static clearscope void AchievementProgressInc( String pvar, int inc, PlayerInfo p = null ) { if ( !p || (p != players[consoleplayer]) ) return; - let cv = CVar.FindCVar(pvar); - if ( !cv ) + let hnd = SWWMStaticHandler(StaticEventHandler.Find("SWWMStaticHandler")); + if ( !hnd ) return; + String pval = hnd.achievementprogress.At(pvar); + if ( pval == "" ) { - if ( developer >= 2 ) Console.Printf("AchievementProgressIncDouble: CVar '"..pvar.."' not found"); + if ( developer >= 2 ) Console.Printf("AchievementProgress: achievement '"..pvar.."' not found"); return; } - double cval = cv.GetFloat(); - cv.SetFloat(cval+inc); + hnd.achievementprogress.Insert(pvar,String.Format("%d",pval.ToInt()+inc)); + } + static clearscope void AchievementProgressIncDouble( String pvar, double inc, PlayerInfo p = null ) + { + if ( !p || (p != players[consoleplayer]) ) return; + let hnd = SWWMStaticHandler(StaticEventHandler.Find("SWWMStaticHandler")); + if ( !hnd ) return; + String pval = hnd.achievementprogress.At(pvar); + if ( pval == "" ) + { + if ( developer >= 2 ) Console.Printf("AchievementProgress: achievement '"..pvar.."' not found"); + return; + } + hnd.achievementprogress.Insert(pvar,String.Format("%g",pval.ToDouble()+inc)); } // gets the names of all mod cvars diff --git a/zscript/weapons/swwm_baseweapon_melee.zsc b/zscript/weapons/swwm_baseweapon_melee.zsc index e0274ccef..b2122b2b5 100644 --- a/zscript/weapons/swwm_baseweapon_melee.zsc +++ b/zscript/weapons/swwm_baseweapon_melee.zsc @@ -138,7 +138,7 @@ Class ParryField : Actor while ( a = Actor(ti.Next()) ) { if ( (justparried.Find(a) < justparried.Size()) || !(SWWMUtility.ValidProjectile(a) || a.bSKULLFLY) || a.bTHRUACTORS || (level.Vec3Diff(a.pos,pos).length() > 80) ) continue; - if ( a is 'Whirlwind' ) SWWMUtility.MarkAchievement('swwm_achievement_tornado',master.player); + if ( a is 'Whirlwind' ) SWWMUtility.MarkAchievement("tornado",master.player); justparried.Push(a); Vector3 vdir = a.vel; Vector3 dir = level.Vec3Diff(master.Vec2OffsetZ(0,0,pos.z),a.pos).unit(); @@ -203,10 +203,10 @@ Class ParryField : Actor } critsnd = true; if ( (a is 'LostSoul') && (master.player.ReadyWeapon is 'SilverBullet') ) - SWWMUtility.MarkAchievement('swwm_achievement_baseball',master.player); + SWWMUtility.MarkAchievement("baseball",master.player); } if ( s ) s.parries++; - SWWMUtility.AchievementProgressInc('swwm_progress_parry',1,master.player); + SWWMUtility.AchievementProgressInc("parry",1,master.player); } if ( --special1 <= 0 ) Destroy(); } diff --git a/zscript/weapons/swwm_blazeit_fx.zsc b/zscript/weapons/swwm_blazeit_fx.zsc index da462bbb0..0e96af7b6 100644 --- a/zscript/weapons/swwm_blazeit_fx.zsc +++ b/zscript/weapons/swwm_blazeit_fx.zsc @@ -697,7 +697,7 @@ Class HellblazerWarhead : HellblazerMissile A_WarheadSub(); if ( special1 >= 40 ) { - if ( target ) SWWMUtility.AchievementProgress('swwm_progress_slayer',invoker.nkill,target.player); + if ( target ) SWWMUtility.AchievementProgress("slayer",invoker.nkill,target.player); Destroy(); } } diff --git a/zscript/weapons/swwm_cbt.zsc b/zscript/weapons/swwm_cbt.zsc index 829338540..d6f563576 100644 --- a/zscript/weapons/swwm_cbt.zsc +++ b/zscript/weapons/swwm_cbt.zsc @@ -451,7 +451,7 @@ Class Wallbuster : SWWMWeapon if ( alertness > louds[which] ) alertness += louds[which]/4; else alertness += louds[which]; } - if ( salts >= 25 ) SWWMUtility.MarkAchievement('swwm_achievement_salt',player); + if ( salts >= 25 ) SWWMUtility.MarkAchievement("salt",player); if ( howmany < 3 ) player.SetPsprite(PSP_WEAPON,ResolveState("FireOne")); else if ( howmany < 15 ) player.SetPsprite(PSP_WEAPON,ResolveState("FireFive")); else player.SetPsprite(PSP_WEAPON,ResolveState("FireTwentyFive")); diff --git a/zscript/weapons/swwm_cbt_fx.zsc b/zscript/weapons/swwm_cbt_fx.zsc index e85fa44c0..76a60df74 100644 --- a/zscript/weapons/swwm_cbt_fx.zsc +++ b/zscript/weapons/swwm_cbt_fx.zsc @@ -351,7 +351,7 @@ Class BusterWall : Thinker { let s = SWWMStats.Find(Instigator.player); if ( s ) s.busts++; - SWWMUtility.AchievementProgressInc('swwm_progress_bustin',1,Instigator.player); + SWWMUtility.AchievementProgressInc("bustin",1,Instigator.player); } bust.busted = true; bust.busttics = 0; diff --git a/zscript/weapons/swwm_danmaku_fx.zsc b/zscript/weapons/swwm_danmaku_fx.zsc index 2d8d50f82..9e3073d4d 100644 --- a/zscript/weapons/swwm_danmaku_fx.zsc +++ b/zscript/weapons/swwm_danmaku_fx.zsc @@ -474,7 +474,7 @@ Class EvisceratorProj : Actor if ( target && tracer && (tracer.bIsMonster||tracer.player) && tracer.IsHostile(target) ) { double dist = level.Vec3Diff(pos,invoker.startpos).length(); - SWWMUtility.AchievementProgress('swwm_progress_lead',int(dist),target.player); + SWWMUtility.AchievementProgress("lead",int(dist),target.player); } bForceXYBillboard = true; A_SetRenderStyle(1.0,STYLE_Add); diff --git a/zscript/weapons/swwm_deathlydeathcannon_fx.zsc b/zscript/weapons/swwm_deathlydeathcannon_fx.zsc index 28d5821c1..409ff3dd4 100644 --- a/zscript/weapons/swwm_deathlydeathcannon_fx.zsc +++ b/zscript/weapons/swwm_deathlydeathcannon_fx.zsc @@ -433,7 +433,7 @@ Class YnykronImpact : Actor if ( tracer.player ) { if ( tracer == target ) - SWWMUtility.MarkAchievement('swwm_achievement_oopsie',tracer.player); + SWWMUtility.MarkAchievement("oopsie",tracer.player); PlayerGone.FeckOff(tracer); } if ( tracer.FindState("YnykronDeath",true) ) @@ -453,7 +453,7 @@ Class YnykronImpact : Actor if ( (tracer.bIsMonster || tracer.player) && tracer.IsHostile(target) && YnykronShot(master) ) YnykronShot(master).enemykills++; if ( target && tracer.FindInventory("EndgameBossMarker") ) - SWWMUtility.MarkAchievement('swwm_achievement_ligma',target.player); + SWWMUtility.MarkAchievement("ligma",target.player); } } if ( YnykronShot(master) ) @@ -1166,8 +1166,8 @@ Class YnykronShot : Actor if ( target && enemykills ) { if ( (enemykills == 1) && !hitboss ) - SWWMUtility.MarkAchievement('swwm_achievement_oneguy',target.player); - SWWMUtility.AchievementProgress('swwm_progress_ezkill',enemykills,target.player); + SWWMUtility.MarkAchievement("oneguy",target.player); + SWWMUtility.AchievementProgress("ezkill",enemykills,target.player); enemykills = 0; } if ( IsActorPlayingSound(CHAN_VOICE) ) @@ -2488,7 +2488,7 @@ Class YnykronSingularity : Actor if ( a.player ) { if ( a == target ) - SWWMUtility.MarkAchievement('swwm_achievement_oopsie',a.player); + SWWMUtility.MarkAchievement("oopsie",a.player); PlayerGone.FeckOff(a); } if ( a.FindState("YnykronAltDeath",true) ) @@ -2501,7 +2501,7 @@ Class YnykronSingularity : Actor IDontFeelSoGood.DeletThis(a,true); // ensures corpse is deleted too } if ( target && a.FindInventory("EndgameBossMarker") ) - SWWMUtility.MarkAchievement('swwm_achievement_ligma',target.player); + SWWMUtility.MarkAchievement("ligma",target.player); } if ( !a || (a.Health <= 0) ) specialf2 += min(100.,capmass*.6); // partial absorption diff --git a/zscript/weapons/swwm_deepdarkimpact.zsc b/zscript/weapons/swwm_deepdarkimpact.zsc index 5ead361e0..bcf79aacd 100644 --- a/zscript/weapons/swwm_deepdarkimpact.zsc +++ b/zscript/weapons/swwm_deepdarkimpact.zsc @@ -234,7 +234,7 @@ Class DeepImpact : SWWMWeapon pb.bAMBUSH = true; } if ( s ) s.parries++; - SWWMUtility.AchievementProgressInc('swwm_progress_parry',1,player); + SWWMUtility.AchievementProgressInc("parry",1,player); } int numpt = Random[Impact](7,12); for ( int i=0; i girth) && is_schutt ) { diff --git a/zscript/weapons/swwm_sparkyboi_fx.zsc b/zscript/weapons/swwm_sparkyboi_fx.zsc index 5938efe5a..9cd789564 100644 --- a/zscript/weapons/swwm_sparkyboi_fx.zsc +++ b/zscript/weapons/swwm_sparkyboi_fx.zsc @@ -1129,7 +1129,7 @@ Class BiosparkBeam : Actor s.Args[0] = t.hitlist[i].hitactor.target.special1; } t.hitlist[i].hitactor.target.Destroy(); - if ( target ) SWWMUtility.AchievementProgressInc('swwm_progress_shock',1,target.player); + if ( target ) SWWMUtility.AchievementProgressInc("shock",1,target.player); } else { diff --git a/zscript/weapons/swwm_splode.zsc b/zscript/weapons/swwm_splode.zsc index b899247c8..7fa5d7a90 100644 --- a/zscript/weapons/swwm_splode.zsc +++ b/zscript/weapons/swwm_splode.zsc @@ -115,7 +115,7 @@ Class ExplodiumGun : SWWMWeapon if ( d.HitActor.IsHostile(self) ) { invoker.deadeyecnt++; - SWWMUtility.AchievementProgress('swwm_progress_deadeye',invoker.deadeyecnt,player); + SWWMUtility.AchievementProgress("deadeye",invoker.deadeyecnt,player); } int dmg = 15; // might as well apply explosion on top @@ -680,7 +680,7 @@ Class DualExplodiumGun : SWWMWeapon if ( d.HitActor.IsHostile(self) ) { ExplodiumGun(invoker.SisterWeapon).deadeyecnt++; - SWWMUtility.AchievementProgress('swwm_progress_deadeye',ExplodiumGun(invoker.SisterWeapon).deadeyecnt,player); + SWWMUtility.AchievementProgress("deadeye",ExplodiumGun(invoker.SisterWeapon).deadeyecnt,player); } int dmg = 15; // might as well apply explosion on top diff --git a/zscript/weapons/swwm_splode_fx.zsc b/zscript/weapons/swwm_splode_fx.zsc index 2a8c51636..d40f47015 100644 --- a/zscript/weapons/swwm_splode_fx.zsc +++ b/zscript/weapons/swwm_splode_fx.zsc @@ -67,7 +67,7 @@ Class ExplodiumMagArm : Actor { int nhit, nkill; [nhit, nkill] = SWWMUtility.DoExplosion(self,2+reactiontime/2,3000+500*reactiontime,40+3*reactiontime,20,DE_COUNTENEMIES); - if ( target && special1 ) SWWMUtility.AchievementProgressInc('swwm_progress_grenade',nkill,target.player); + if ( target && special1 ) SWWMUtility.AchievementProgressInc("grenade",nkill,target.player); } Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,5); let s = Spawn("SWWMHalfSmoke",pos); @@ -160,7 +160,7 @@ Class ExplodiumMagProj : Actor A_AlertMonsters(swwm_uncapalert?0:6000); int nhit, nkill; [nhit, nkill] = SWWMUtility.DoExplosion(self,10+20*special1,80000+8000*special1,90+10*special1,60,DE_EXTRAZTHRUST|DE_COUNTENEMIES); - if ( target && isplanted ) SWWMUtility.AchievementProgressInc('swwm_progress_grenade',nkill,target.player); + if ( target && isplanted ) SWWMUtility.AchievementProgressInc("grenade",nkill,target.player); A_QuakeEx(9,9,9,30,0,400+80*special1,"",QF_RELATIVE|QF_SCALEDOWN,falloff:300,rollintensity:2.); A_StartSound("explodium/maghit",CHAN_VOICE,attenuation:.35); A_StartSound("explodium/maghit",CHAN_WEAPON,attenuation:.2); diff --git a/zscript/weapons/swwm_tastytreat_fx.zsc b/zscript/weapons/swwm_tastytreat_fx.zsc index 410822cb6..34f4fd74d 100644 --- a/zscript/weapons/swwm_tastytreat_fx.zsc +++ b/zscript/weapons/swwm_tastytreat_fx.zsc @@ -560,7 +560,7 @@ Class CandyGunProj : Actor } } if ( bossbrains && target ) - SWWMUtility.MarkAchievement('swwm_achievement_yeet',target.player); + SWWMUtility.MarkAchievement("yeet",target.player); angle = atan2(cvel.y,cvel.x); pitch = asin(-cvel.z); bNOGRAVITY = true; diff --git a/zscript/weapons/swwm_thiccboolet.zsc b/zscript/weapons/swwm_thiccboolet.zsc index e66c1b4e8..f6eb3ba3c 100644 --- a/zscript/weapons/swwm_thiccboolet.zsc +++ b/zscript/weapons/swwm_thiccboolet.zsc @@ -405,8 +405,8 @@ Class SilverBullet : SWWMWeapon if ( t.HitList[i].HitActor && (t.HitList[i].HitActor.Health <= 0) && (t.HitList[i].HitActor.bIsMonster || t.HitList[i].HitActor.player) && t.HitList[i].HitActor.IsHostile(self) ) { invoker.nkills++; - SWWMUtility.AchievementProgress('swwm_progress_conga',invoker.nkills,player); - if ( t.Hitlist[i].pastwall ) SWWMUtility.AchievementProgressInc('swwm_progress_thruwall',1,player); + SWWMUtility.AchievementProgress("conga",invoker.nkills,player); + if ( t.Hitlist[i].pastwall ) SWWMUtility.AchievementProgressInc("thruwall",1,player); } if ( t.HitList[i].HitActor && !t.HitList[i].HitActor.bNOBLOOD && !t.HitList[i].HitActor.bDORMANT ) { diff --git a/zscript/weapons/swwm_thiccboolet_fx.zsc b/zscript/weapons/swwm_thiccboolet_fx.zsc index 96250bed2..bf19adc43 100644 --- a/zscript/weapons/swwm_thiccboolet_fx.zsc +++ b/zscript/weapons/swwm_thiccboolet_fx.zsc @@ -60,8 +60,8 @@ Class SilverAirRip : Actor if ( SilverBullet(master) ) { Silverbullet(master).nkills += nkill; - SWWMUtility.AchievementProgress('swwm_progress_conga',Silverbullet(master).nkills,target.player); - if ( bAMBUSH ) SWWMUtility.AchievementProgressInc('swwm_progress_thruwall',nkill,target.player); + SWWMUtility.AchievementProgress("conga",Silverbullet(master).nkills,target.player); + if ( bAMBUSH ) SWWMUtility.AchievementProgressInc("thruwall",nkill,target.player); } Destroy(); } @@ -112,8 +112,8 @@ Class SilverImpact : Actor if ( SilverBullet(master) ) { Silverbullet(master).nkills += nkill; - SWWMUtility.AchievementProgress('swwm_progress_conga',Silverbullet(master).nkills,target.player); - if ( bAMBUSH ) SWWMUtility.AchievementProgressInc('swwm_progress_thruwall',nkill,target.player); + SWWMUtility.AchievementProgress("conga",Silverbullet(master).nkills,target.player); + if ( bAMBUSH ) SWWMUtility.AchievementProgressInc("thruwall",nkill,target.player); } A_AlertMonsters(swwm_uncapalert?0:2500); A_QuakeEx(4,4,4,20,0,400,"",QF_RELATIVE|QF_SCALEDOWN,falloff:100,rollIntensity:.9);