Begginings of achievement system.

Fix projectile detection.
This commit is contained in:
Mari the Deer 2021-03-22 01:26:15 +01:00
commit 1cbfd4b97d
20 changed files with 1369 additions and 35 deletions

View file

@ -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;

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

View file

@ -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";

View file

@ -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";

View file

@ -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-";

View file

@ -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"

View file

@ -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;

View file

@ -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]());

View file

@ -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") )

View file

@ -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.Size(); i++ )
{
let c = (Class<SWWMCollectible>)(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<vars.Size(); i++ )
{
if ( ignoreme[i] ) continue;
if ( !CheckAchievement(vars[i],names[i],number[i],pvar[i]) )
alldone = false;
}
let ev = CVar.FindCVar('swwm_achievement_everything');
int val = ev.GetInt();
// not done!
if ( !alldone )
{
if ( val != 0 ) ev.SetInt(0);
return;
}
// all done!
if ( val == 0 ) ev.SetInt(1);
else if ( (val == 1) && (gametic > 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;
}
}
}

View file

@ -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<fadeintics)?(tics/fadeintics):(tics<(fadeintics+holdtics))?1.:(1.-(tics-(fadeintics+holdtics))/fadeouttics);
Vector2 pos = (int(ss.x-232)/2,(ss.y-(margin+36))+int(margin+40)*(1.-alpha));
String loctag = StringTable.Localize(tag);
String loctxt = num?String.Format(StringTable.Localize(txt),num):StringTable.Localize(txt);
BrokenLines l = fnt2.BreakLines(loctxt,176);
int th = 14+(9*l.Count());
Screen.DrawTexture(frame,false,pos.x,pos.y,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
if ( icon.IsValid() ) Screen.DrawTexture(icon,false,pos.x+2,pos.y+2,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
int yy = 2+(32-th)/2;
Screen.DrawText(fnt,Font.CR_GREEN,pos.x+40,pos.y+yy,loctag,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
yy += 14;
for ( int i=0; i<l.Count(); i++ )
{
Screen.DrawText(fnt2,Font.CR_WHITE,pos.x+46,pos.y+yy,l.StringAt(i),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
yy += 9;
}
}
}

View file

@ -481,10 +481,11 @@ Class PartyTime : Actor
}
action void A_Confetti()
{
if ( !bAMBUSH ) A_StartSound("misc/tada",CHAN_ITEM);
if ( !bAMBUSH && !bSTANDSTILL ) A_StartSound("misc/tada",CHAN_ITEM);
double ang, pt;
int numpt = Random[ExploS](100,120);
if ( bAMBUSH ) numpt *= 4;
else if ( bSTANDSTILL ) numpt *= 2;
for ( int i=0; i<numpt; i++ )
{
ang = FRandom[ExploS](0,360);

View file

@ -13,6 +13,14 @@ Class MenuTransaction
bool result, usedup;
}
Class MenuAchievement
{
String tag, txt;
TextureID icon;
CVar state, progress;
int num, maxval;
}
// FIXME this whole thing needs to be refactored eventually
Class DemolitionistMenu : GenericMenu
{
@ -39,7 +47,7 @@ Class DemolitionistMenu : GenericMenu
};
TextureID MainWindow, TabSeparator, WindowSeparator, WindowSeparatorH,
FancyBg, Drawing[3], LoreSeparator, LoreSeparatorW;
FancyBg, Drawing[3], LoreSeparator, LoreSeparatorW, AchievementUnknown;
transient Font TewiFont, MPlusFont, MiniwiFont, k6x8Font;
Array<int> tabs;
int curtab, oldtab;
@ -57,6 +65,7 @@ Class DemolitionistMenu : GenericMenu
Array<MonsterKill> sorted_mstats; // sorted by killcount
Array<LevelStat> filtered_lstats; // filtered if necessary + entry for current map
LevelStat curlstat;
Array<MenuAchievement> achievements; // array created once, then sorted as needed
// inventory lists
Array<Inventory> 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<vars.Size(); i++ )
{
if ( ignoreme[i] ) continue;
let ac = new("MenuAchievement");
ac.tag = names[i].."_TAG";
ac.txt = names[i].."_TXT";
ac.icon = TexMan.CheckForTexture(StringTable.Localize(names[i].."_PIC"),TexMan.Type_Any);
if ( !ac.icon.IsValid() ) ac.icon = TexMan.CheckForTexture("graphics/Achievements/AchievementNone.png",TexMan.Type_Any);
ac.state = CVar.FindCVar(vars[i]);
ac.progress = (pvar[i]!='None')?CVar.FindCVar(pvar[i]):null;
ac.maxval = ac.num = number[i];
// special cases
if ( vars[i] == 'swwm_achievement_allcoll' )
{
int nc = 0;
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let c = (Class<SWWMCollectible>)(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<MenuAchievement> 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<MenuAchievement> 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<checklist.Size(); i++ )
{
@ -3030,10 +3590,58 @@ Class DemolitionistMenu : GenericMenu
}
else if ( sel1 == STAT_ACHIEVEMENT )
{
xx += 9;
yy = 23;
str = StringTable.Localize("$SWWM_COMINGSOON");
Screen.DrawText(fnt,Font.CR_FIRE,origin.x+xx+int((631-xx)-fnt.StringWidth(str))/2,origin.y+(400-fnt.GetHeight())/2,str,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
xx += 12;
yy = 26;
int cnt = achievements.Size();
int ofs = clamp(sel0,0,max(0,cnt-7));
let fnt2 = LangFont(MiniwiFont);
int barsz = (language~=="jp")?400:480;
int txtsz = (language~=="jp")?360:440;
for ( int i=ofs; i<cnt; i++ )
{
if ( yy >= 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<l.Count(); j++ )
Screen.DrawText(fnt2,completed?Font.CR_WHITE:Font.CR_BLACK,origin.x+xx+40,origin.y+yy+oy+14+j*9,l.StringAt(j),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
yy += 50;
}
// scrollbar
if ( cnt > 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)) )

View file

@ -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 )

View file

@ -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')

View file

@ -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<blocks; i++ ) str.AppendCharacter(0x258F);
if ( eblocks )
{
str.AppendCharacter(0x1C);
str.AppendCharacter(0x41+bcol);
}
for ( int i=0; i<eblocks; i++ ) str.AppendCharacter(0x258F);
if ( blocks || eblocks )
{
str.AppendCharacter(0x1C);
str.AppendCharacter(0x2D);
}
return str;
}
static clearscope void ObscureText( out String str, int seed )
{
int len = str.CodePointCount();
String newstr = "";
for ( int i=0, pos=0; i<len; i++ )
{
seed = ((seed<<1)*35447+(seed/87));
int ch;
[ch, pos] = str.GetNextCodePoint(pos);
if ( (ch == 0x20) || (ch == 0x09) || (ch == 0x0A) )
newstr.AppendCharacter(ch);
else newstr.AppendCharacter((abs(seed)%95)+32);
}
str = newstr;
}
static clearscope void BeautifyClassName( out String str )
{
String workstr = str;
@ -898,6 +939,28 @@ Class SWWMUtility
return false;
}
// IsZeroDamage() can lead to some false negatives, we have to account for that
static play bool ValidProjectile( Actor a )
{
if ( !a.bMISSILE ) return false;
if ( a is 'AirBullet' ) return true;
if ( a is 'PusherProjectile' ) return true;
if ( a is 'ExplodiumMagProj' ) return true;
if ( a is 'CorrosiveFlechette' ) return true;
if ( a is 'TheBall' ) return true;
if ( a is 'EvisceratorChunk' ) return true;
if ( a is 'EvisceratorProj' ) return true;
if ( a is 'HellblazerMissile' ) return true;
if ( a is 'BigBiospark' ) return true;
if ( a is 'BiosparkBall' ) return true;
if ( a is 'BiosparkCore' ) return true;
if ( a is 'CandyGunProj' ) return true;
if ( a is 'CandyMagProj' ) return true;
if ( a is 'LoveHeart' ) return true;
if ( !a.IsZeroDamage() ) return true;
return false;
}
static clearscope bool IdentifyingDog( Actor a )
{
if ( a is 'MBFHelperDog' ) return true;

View file

@ -136,7 +136,7 @@ Class ParryField : Actor
Actor a;
while ( a = Actor(ti.Next()) )
{
if ( !((a.bMISSILE && !a.IsZeroDamage() && (a.target != master)) || a.bSKULLFLY) || a.bTHRUACTORS || (level.Vec3Diff(a.pos,pos).length() > 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;

View file

@ -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;