Achievement system overhaul.

Continuin the menu rewrite.
This commit is contained in:
Mari the Deer 2021-09-20 19:22:42 +02:00
commit 8176b21b8c
53 changed files with 585 additions and 518 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

BIN
graphics/KBase/FrameTex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

BIN
graphics/KBase/HSepTex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 B

BIN
graphics/KBase/VSepTex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 B

View file

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

View file

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

View file

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

View file

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

View file

@ -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<MAXPLAYERS; i++ )
@ -126,31 +126,31 @@ extend Class SWWMHandler
}
if ( collected ) break;
}
if ( !collected ) SWWMUtility.MarkAchievement('swwm_achievement_cliffyb',players[consoleplayer]);
if ( !collected ) SWWMUtility.MarkAchievement("cliffyb",players[consoleplayer]);
}
// these can't be done on hexen
if ( gameinfo.GameType&GAME_Hexen ) return;
// beat the par time?
if ( level.partime && (Thinker.Tics2Seconds(level.maptime) <= level.partime) )
SWWMUtility.AchievementProgressInc('swwm_progress_par',1,players[consoleplayer]);
SWWMUtility.AchievementProgressInc("par",1,players[consoleplayer]);
// blaze it?
if ( Thinker.Tics2Seconds(level.maptime) == 260 )
SWWMUtility.MarkAchievement('swwm_achievement_blaze',players[consoleplayer]);
SWWMUtility.MarkAchievement("blaze",players[consoleplayer]);
// one standing?
if ( (level.total_monsters-level.killed_monsters) == 1 )
SWWMUtility.MarkAchievement('swwm_achievement_onestanding',players[consoleplayer]);
SWWMUtility.MarkAchievement("onestanding",players[consoleplayer]);
// nice?
if ( players[consoleplayer].Health == 69 )
SWWMUtility.MarkAchievement('swwm_achievement_nice',players[consoleplayer]);
SWWMUtility.MarkAchievement("nice",players[consoleplayer]);
// peaceful/untouchable?
if ( !dealtdamage[consoleplayer] )
SWWMUtility.MarkAchievement('swwm_achievement_peace',players[consoleplayer]);
SWWMUtility.MarkAchievement("peace",players[consoleplayer]);
if ( !reallytookdamage[consoleplayer] )
SWWMUtility.MarkAchievement('swwm_achievement_untouchable',players[consoleplayer]);
SWWMUtility.MarkAchievement("untouchable",players[consoleplayer]);
// in a hurry?
if ( ((level.total_monsters > 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 )

View file

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

View file

@ -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<SWWMAchievement> achievements;
Dictionary achievementstate, achievementprogress;
Array<SWWMAchievementInfo> 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<achievements.Size(); i++ )
for ( int i=0; i<achievementinfo.Size(); i++ )
{
// this one is updated outside the loop
if ( achievements[i].basename == "everything" )
if ( achievementinfo[i].basename == "everything" )
{
ev = i;
continue;
}
if ( !CheckAchievement(achievements[i]) )
if ( !CheckAchievement(achievementinfo[i]) )
alldone = false;
}
if ( ev == -1 ) return; // should not happen, though
int val = achievements[ev].state.GetInt();
int val = achievementstate.At("everything").ToInt();
// not done!
if ( !alldone )
{
if ( val != 0 ) achievements[ev].state.SetInt(0);
if ( val != 0 ) achievementstate.Insert("everything","0");
return;
}
// all done!
if ( val == 0 ) achievements[ev].state.SetInt(1);
if ( val == 0 ) achievementstate.Insert("everything","1");
else if ( (val == 1) && (gametic > 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<SWWMAchievementInfo> achievements )
{
achievements.Clear();
let lmp = Wads.FindLump("achievements.lst");
if ( lmp == -1 ) ThrowAbortException("'achievements.lst' not found");
String dat;
Array<String> 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<list.Size(); i++ )
{
if ( (list[i].Length() == 0) || (list[i].Left(1) == "#") || (list[i].Left(1) == "") )
continue;
ln.Clear();
list[i].Split(ln,",",0);
// game filtering
if ( !(gameinfo.gametype&GAME_DOOM) && (ln[3] ~== "doom") ) continue;
else if ( !(gameinfo.gametype&GAME_HERETIC) && (ln[3] ~== "heretic") ) continue;
else if ( !(gameinfo.gametype&GAME_HEXEN) && (ln[3] ~== "hexen") ) continue;
else if ( !(gameinfo.gametype&GAME_RAVEN) && (ln[3] ~== "raven") ) continue;
else if ( !(gameinfo.gametype&(GAME_DOOM|GAME_HERETIC)) && (ln[3] ~== "nothexen") ) continue;
let ac = new("SWWMAchievementInfo");
ac.baseindex = bidx;
ac.basename = ln[0];
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);
ac.maxval = ln[1].ToInt();
// special case for maxval
if ( ac.maxval && (ac.basename == "allcoll") )
{
int nc = 0;
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let c = (Class<SWWMCollectible>)(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<statestr.length(); i+=2 )
{
int b, c, a;
b = statestr.ByteAt(i);
c = statestr.ByteAt(i+1);
a = ((b-0x41)|((c-0x41)<<4))^cypher[(i/2)%4];
nstr.AppendCharacter(a);
}
statestr = nstr;
nstr = "";
for ( int i=0; i<progstr.length(); i+=2 )
{
int b, c, a;
b = progstr.ByteAt(i);
c = progstr.ByteAt(i+1);
a = ((b-0x41)|((c-0x41)<<4))^cypher[(i/2)%4];
nstr.AppendCharacter(a);
}
progstr = nstr;
// no key separator?
if ( (statestr.IndexOf(",") == -1) || (progstr.IndexOf(",") == -1) )
{
CreateAchievements();
return;
}
// create dictionaries
achievementstate = Dictionary.Create();
achievementprogress = Dictionary.Create();
Array<String> keys;
keys.Clear();
statestr.Split(keys,",");
for ( int i=0; i<keys.Size(); i++ )
{
int colon = keys[i].IndexOf(":");
// no value separator?
if ( colon == -1 )
{
CreateAchievements();
return;
}
achievementstate.Insert(keys[i].Left(colon),keys[i].Mid(colon+1));
}
keys.Clear();
progstr.Split(keys,",");
for ( int i=0; i<keys.Size(); i++ )
{
int colon = keys[i].IndexOf(":");
// no value separator?
if ( colon == -1 )
{
CreateAchievements();
return;
}
achievementprogress.Insert(keys[i].Left(colon),keys[i].Mid(colon+1));
}
// load achievement info and trim any bogus keys
ParseAchievementList(achievementinfo);
let di = DictionaryIterator.Create(achievementstate);
while ( di.Next() )
{
String key = di.Key();
bool deleteme = true;
for ( int i=0; i<achievementinfo.Size(); i++ )
{
if ( achievementinfo[i].basename != key ) continue;
deleteme = false;
break;
}
}
di = DictionaryIterator.Create(achievementprogress);
while ( di.Next() )
{
String key = di.Key();
bool deleteme = true;
for ( int i=0; i<achievementinfo.Size(); i++ )
{
if ( achievementinfo[i].basename != key ) continue;
if ( !achievementinfo[i].maxval ) continue;
deleteme = false;
break;
}
}
}
// save all achievement state and progress
private void SaveAchievements()
{
String statestr = achievementstate.ToString();
String progstr = achievementprogress.ToString();
// trim unneeded json stuff
statestr.Replace("{","");
statestr.Replace("}","");
statestr.Replace("\"","");
progstr.Replace("{","");
progstr.Replace("}","");
progstr.Replace("\"","");
// cheap encode
int cypher[] = {0xAD,0xEA,0xDB,0xED};
String nstr = "";
for ( int i=0; i<statestr.length(); i++ )
{
int a, b, c;
a = statestr.ByteAt(i)^cypher[i%4];
b = (a&0x0F)+0x41;
c = ((a&0xF0)>>4)+0x41;
nstr.AppendFormat("%c%c",b,c);
}
statestr = nstr;
nstr = "";
for ( int i=0; i<progstr.length(); i++ )
{
int a, b, c;
a = progstr.ByteAt(i)^cypher[i%4];
b = (a&0x0F)+0x41;
c = ((a&0xF0)>>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<achievementinfo.Size(); i++ )
{
achievementstate.Insert(achievementinfo[i].basename,"0");
if ( !achievementinfo[i].maxval ) continue;
achievementprogress.Insert(achievementinfo[i].basename,"0");
}
}
// migrate from old individual CVars
private void MigrateAchievements()
{
achievementstate = Dictionary.Create();
achievementprogress = Dictionary.Create();
ParseAchievementList(achievementinfo);
CVar cv;
for ( int i=0; i<achievementinfo.Size(); i++ )
{
String val = "0";
cv = CVar.FindCVar("swwm_achievement_"..achievementinfo[i].basename);
if ( cv ) val = cv.GetString();
achievementstate.Insert(achievementinfo[i].basename,val);
if ( !achievementinfo[i].maxval ) continue;
val = "0";
cv = CVar.FindCVar("swwm_progress_"..achievementinfo[i].basename);
if ( cv ) val = cv.GetString();
achievementprogress.Insert(achievementinfo[i].basename,val);
}
}
}

View file

@ -404,7 +404,7 @@ Class SWWMStatusBar : BaseStatusBar
{
EventHandler.SendNetworkEvent("swwmstorepuzzlecnt",consoleplayer,puzzlecnt,realpuzzlecnt);
int tpuz = SWWMUtility.IsDeathkings()?15:19;
if ( realpuzzlecnt >= tpuz ) SWWMUtility.MarkAchievement('swwm_achievement_puzzle',players[consoleplayer]);
if ( realpuzzlecnt >= tpuz ) SWWMUtility.MarkAchievement("puzzle",players[consoleplayer]);
if ( !swwm_nomapmsg )
{
switch ( puzzlecnt )

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,7 +6,8 @@ Class SWWMAchievementMenu : GenericMenu
// so put everything in here
TextureID AchievementUnknown, SelectBox, BaseBox;
bool ShouldObscure;
Array<SWWMAchievement> mItems;
SWWMStaticHandler hnd;
Array<SWWMAchievementInfo> 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<mItems.Size(); i++ )
{
String key = mItems[i].basename;
// cache state/progress
mItems[i].state = hnd.achievementstate.At(key).ToInt();
if ( mItems[i].maxval )
{
mItems[i].val = hnd.achievementprogress.At(key).ToInt();
}
// check if we need to hide it
if ( (key == "everything") && !mItems[i].state )
{
mItems.Delete(i);
i--;
continue;
}
if ( !dohide || mItems[i].state || (mItems[i].maxval && mItems[i].val) ) continue;
mItems.Delete(i);
i--;
}
ShouldObscure = (swwm_filterachievements==1);
AchievementUnknown = TexMan.CheckForTexture("graphics/Achievements/HiddenAchievement.png",TexMan.Type_Any);
SelectBox = TexMan.CheckForTexture("graphics/Achievements/SelectAchievement.png",TexMan.Type_Any);
@ -34,8 +57,8 @@ Class SWWMAchievementMenu : GenericMenu
incomplete = 0;
for ( int i=0; i<mItems.Size(); i++ )
{
if ( !!mItems[i].state.GetInt() ) completed++;
else if ( mItems[i].progress && mItems[i].progress.GetInt() ) incomplete++;
if ( !!(hnd.achievementstate.At(mItems[i].basename).ToInt()) ) completed++;
else if ( mItems[i].maxval && mItems[i].val ) incomplete++;
}
}
@ -52,23 +75,23 @@ Class SWWMAchievementMenu : GenericMenu
{
// detailed achievement information
let a = mItems[mSelected];
bool completed = !!a.state.GetInt();
bool hasprogress = (a.progress && a.progress.GetInt());
bool completed = !!a.state;
bool hasprogress = (a.maxval && a.val);
String str = StringTable.Localize("$SWWM_ACHIEVEMENT_"..a.basename.."_TAG");
if ( !completed && !hasprogress && ShouldObscure ) SWWMUtility.ObscureText(str,gametic/3);
int xx = (Screen.GetWidth()-newsmallfont.StringWidth(str)*CleanXFac_1)/2;
int yy = y;
if ( !a.progress || (ShouldObscure && !hasprogress) ) yy += ((newsmallfont.GetHeight()+2)*CleanYFac_1)/2;
if ( !a.maxval || (ShouldObscure && !hasprogress) ) yy += ((newsmallfont.GetHeight()+2)*CleanYFac_1)/2;
Screen.DrawText(newsmallfont,completed?Font.CR_GREEN:Font.CR_DARKGRAY,xx,yy,str,DTA_CleanNoMove_1,true);
yy += (newsmallfont.GetHeight()+2)*CleanYFac_1;
str = a.hasformat?String.Format(StringTable.Localize("$SWWM_ACHIEVEMENT_"..a.basename.."_TXT"),a.maxval):StringTable.Localize("$SWWM_ACHIEVEMENT_"..a.basename.."_TXT");
if ( !completed && !hasprogress && ShouldObscure ) SWWMUtility.ObscureText(str,(gametic/3)+1);
xx = (Screen.GetWidth()-newsmallfont.StringWidth(str)*CleanXFac_1)/2;
Screen.DrawText(newsmallfont,completed?Font.CR_WHITE:Font.CR_BLACK,xx,yy,str,DTA_CleanNoMove_1,true);
if ( a.progress && (!ShouldObscure || hasprogress) )
if ( a.maxval && (!ShouldObscure || hasprogress) )
{
yy += (newsmallfont.GetHeight()+2)*CleanYFac_1;
int val = a.progress.GetInt();
int val = a.val;
val = clamp(val,0,a.maxval);
if ( completed ) str = String.Format("%s / %s",SWWMUtility.ThousandsNum(a.maxval),SWWMUtility.ThousandsNum(a.maxval));
else str = String.Format("%s / %s",SWWMUtility.ThousandsNum(val),SWWMUtility.ThousandsNum(a.maxval));
@ -146,28 +169,25 @@ Class SWWMAchievementMenu : GenericMenu
override bool MouseEvent( int type, int mx, int my )
{
bool res = Super.MouseEvent(type,mx,my);
if ( type == MOUSE_Click )
int xx = (Screen.GetWidth()-480*CleanXFac_1)/2;
int yy = mBaseY;
for ( int i=0; i<mItems.Size(); i++ )
{
int xx = (Screen.GetWidth()-480*CleanXFac_1)/2;
int yy = mBaseY;
for ( int i=0; i<mItems.Size(); i++ )
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) )
{
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<mItems.Size(); i++ )
{
let a = mItems[i];
bool completed = !!a.state.GetInt();
bool hasprogress = (a.progress && a.progress.GetInt());
bool completed = !!a.state;
bool hasprogress = (a.maxval && a.val);
Screen.DrawTexture(BaseBox,false,xx+5*CleanXFac_1,yy+5*CleanYFac_1,DTA_CleanNoMove_1,true,DTA_FillColor,(!completed&&!hasprogress&&ShouldObscure)?Color(8,8,8):Color(16,16,16));
Screen.DrawTexture((!completed&&!hasprogress&&ShouldObscure)?AchievementUnknown:a.icon,false,xx+4*CleanXFac_1,yy+4*CleanYFac_1,DTA_CleanNoMove_1,true,DTA_Desaturate,(!completed)*255,DTA_ColorOverlay,completed?Color(0,0,0,0):(hasprogress||!ShouldObscure)?Color(96,0,0,0):Color(192,0,0,0));
if ( mSelected == i )
Screen.DrawTexture(SelectBox,false,xx,yy,DTA_CleanNoMove_1,true);
if ( mSelected == i ) Screen.DrawTexture(SelectBox,false,xx,yy,DTA_CleanNoMove_1,true);
xx += 40*CleanXFac_1;
if ( !((i+1)%12) )
{

View file

@ -70,7 +70,7 @@ Class SWWMGesture : SWWMWeapon
// check if we can see it
if ( !SWWMUtility.InPlayerFOV(Owner.player,a) ) continue;
// someone's dying
SWWMUtility.MarkAchievement('swwm_achievement_wave',Owner.player);
SWWMUtility.MarkAchievement("wave",Owner.player);
break;
}
}
@ -252,7 +252,7 @@ Class SWWMGesture : SWWMWeapon
let s = Demolitionist(self).mystats;
if ( s ) s.befriend++;
if ( SWWMUtility.IdentifyingCaco(t) || SWWMUtility.IdentifyingDrug(t) || SWWMUtility.IdentifyingDoubleBoi(t) )
SWWMUtility.AchievementProgressInc('swwm_progress_friend',1,player);
SWWMUtility.AchievementProgressInc("friend",1,player);
}
t.bFRIENDLY = true;
if ( deathmatch )

View file

@ -305,7 +305,7 @@ Class LoveHeart : Actor
if ( target && target.player )
{
int scr = (TexMan.GetName(HitTexture).Left(6)~=="ZZWOLF")?200:20;
if ( scr == 20 ) SWWMUtility.AchievementProgressInc('swwm_progress_doodle',1,player);
if ( scr == 20 ) SWWMUtility.AchievementProgressInc("doodle",1,player);
SWWMCredits.Give(target.player,scr);
if ( target.player == players[consoleplayer] ) SWWMScoreObj.Spawn(scr,pos);
}
@ -587,7 +587,7 @@ Class HeadpatTracker : Actor
patter.player.cheats |= CF_TOTALLYFROZEN;
Demolitionist(patter).scriptedinvul = true;
target.bDORMANT = true;
if ( SWWMUtility.IdentifyingDog(target) ) SWWMUtility.MarkAchievement('swwm_achievement_mbf',user.player);
if ( SWWMUtility.IdentifyingDog(target) ) SWWMUtility.MarkAchievement("mbf",user.player);
return true;
}
return false;

View file

@ -159,7 +159,7 @@ Class SWWMHandler : EventHandler
if ( (!w || !w.wallponch) && (!(e.Thing is 'Demolitionist') || !Demolitionist(e.Thing).hitactivate) ) return;
let s = SWWMStats.Find(e.Thing.player);
if ( s ) s.wponch++;
SWWMUtility.AchievementProgressInc('swwm_progress_slemg',1,e.Thing.player);
SWWMUtility.AchievementProgressInc("slemg",1,e.Thing.player);
}
// stuff for hud

View file

@ -49,7 +49,7 @@ Class SWWMHangingKeen : Actor
action void A_DropKeen()
{
Spawn("SWWMDroppedKeen",Vec3Offset(0,0,8));
SWWMUtility.MarkAchievement('swwm_achievement_keen',players[consoleplayer]);
if ( target ) SWWMUtility.MarkAchievement("keen",target.player);
}
override bool Used( Actor user )
{

View file

@ -462,13 +462,13 @@ Class Demolitionist : PlayerPawn
if ( !(player.cmd.buttons&BT_USER2) ) dashboost *= .1;
}
double fueluse = (dashfuel-max(0.,dashfuel-dashboost))/60.;
SWWMUtility.AchievementProgressIncDouble('swwm_progress_fuel',fueluse,player);
SWWMUtility.AchievementProgressIncDouble("fuel",fueluse,player);
mystats.fuelusage += fueluse;
if ( !swwm_superfuel ) dashfuel = max(0.,dashfuel-dashboost);
dashcooldown = min(40,max(10,int(dashcooldown*1.4)));
fuelcooldown = max(30,fuelcooldown);
if ( (dashfuel <= 0.) && fullfuel )
SWWMUtility.AchievementProgressInc('swwm_progress_brake',1,player);
SWWMUtility.AchievementProgressInc("brake",1,player);
if ( (dashfuel <= 0.) || (dashboost <= 0.) )
SetStateLabel("DashEnd");
}
@ -484,7 +484,7 @@ Class Demolitionist : PlayerPawn
last_boost = level.maptime+1;
}
double fueluse = (dashfuel-max(0.,dashfuel-dashboost))/60.;
SWWMUtility.AchievementProgressIncDouble('swwm_progress_fuel',fueluse,player);
SWWMUtility.AchievementProgressIncDouble("fuel",fueluse,player);
mystats.fuelusage += fueluse;
if ( !swwm_superfuel ) dashfuel = max(0.,dashfuel-dashboost);
if ( ((dashfuel <= 0.) || (dashboost <= 0.)) )
@ -529,7 +529,7 @@ Class Demolitionist : PlayerPawn
A_StartSound("bestsound",CHAN_ITEMEXTRA,CHANF_OVERLAP);
lastbump *= .97;
int scr = (TexMan.GetName(d.HitTexture).Left(6)~=="ZZWOLF")?200:20;
if ( scr == 20 ) SWWMUtility.AchievementProgressInc('swwm_progress_doodle',1,player);
if ( scr == 20 ) SWWMUtility.AchievementProgressInc("doodle",1,player);
SWWMCredits.Give(player,scr);
if ( player == players[consoleplayer] ) SWWMScoreObj.Spawn(scr,d.HitLocation);
if ( d.HitType == TRACE_HitWall )
@ -1027,7 +1027,7 @@ Class Demolitionist : PlayerPawn
{
cairtime = 0;
mystats.grounddist += traveldist;
SWWMUtility.AchievementProgressIncDouble('swwm_progress_travel',traveldist/32000.,player);
SWWMUtility.AchievementProgressIncDouble("travel",traveldist/32000.,player);
}
}
else mystats.swimdist += traveldist;
@ -1035,7 +1035,7 @@ Class Demolitionist : PlayerPawn
if ( player.cmd.buttons&BT_USER3 ) SenseItems();
if ( vel.length() > 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);

View file

@ -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<achievements.Size(); i++ )
for ( int i=0; i<achievementinfo.Size(); i++ )
{
achievements[i].state.SetInt(0);
if ( achievements[i].progress )
achievements[i].progress.SetInt(0);
achievementstate.Insert(achievementinfo[i].basename,"0");
if ( achievementinfo[i].maxval )
achievementprogress.Insert(achievementinfo[i].basename,"0");
}
}
else if ( e.Name ~== "swwmdumpachievements" )
{
if ( achievements.Size() <= 0 )
SWWMUtility.LoadAchievements(achievements);
for ( int i=0; i<achievements.Size(); i++ )
Console.Printf("swwm_achievement_"..achievements[i].basename.."="..achievements[i].state.GetString());
for ( int i=0; i<achievements.Size(); i++ )
{
if ( !achievements[i].progress ) continue;
Console.Printf("swwm_progress_"..achievements[i].basename.."="..achievements[i].progress.GetString());
}
Console.Printf("---STATE---");
let di = DictionaryIterator.Create(achievementstate);
while ( di.Next() )
Console.Printf("%s = %s",di.Key(),di.Value());
Console.Printf("---PROGRESS---");
di = DictionaryIterator.Create(achievementprogress);
while ( di.Next() )
Console.Printf("%s = %s",di.Key(),di.Value());
}
else if ( e.Name ~== "swwmgetversion" )
{

View file

@ -430,7 +430,7 @@ Class SWWMFlyTracker : Thinker
{
gracepd++;
if ( gracepd < 10 ) return;
if ( instigator ) SWWMUtility.AchievementProgress('swwm_progress_flight',int(maxdist),instigator.player);
if ( instigator ) SWWMUtility.AchievementProgress("flight",int(maxdist),instigator.player);
Destroy();
return;
}

View file

@ -226,10 +226,10 @@ Class SWWMCredits : Thinker
}
SWWMLoreLibrary.Add(p,"ScoreSystem");
if ( cheat ) return;
int curamt = swwm_progress_dosh;
int curamt = SWWMUtility.GetAchievementProgress("dosh");
if ( (hamount > 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 )

View file

@ -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<SWWMAchievement> achievements, bool filter = false )
{
achievements.Clear();
let lmp = Wads.FindLump("achievements.lst");
if ( lmp == -1 ) ThrowAbortException("'achievements.lst' not found");
String dat;
Array<String> 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<list.Size(); i++ )
{
if ( (list[i].Length() == 0) || (list[i].Left(1) == "#") || (list[i].Left(1) == "") )
continue;
ln.Clear();
list[i].Split(ln,",",0);
// game filtering
if ( !(gameinfo.gametype&GAME_DOOM) && (ln[3] ~== "doom") ) continue;
else if ( !(gameinfo.gametype&GAME_HERETIC) && (ln[3] ~== "heretic") ) continue;
else if ( !(gameinfo.gametype&GAME_HEXEN) && (ln[3] ~== "hexen") ) continue;
else if ( !(gameinfo.gametype&GAME_RAVEN) && (ln[3] ~== "raven") ) continue;
else if ( !(gameinfo.gametype&(GAME_DOOM|GAME_HERETIC)) && (ln[3] ~== "nothexen") ) continue;
let ac = new("SWWMAchievement");
ac.baseindex = bidx;
ac.basename = ln[0];
ac.maxval = ln[1].ToInt();
ac.state = CVar.FindCVar("swwm_achievement_"..ac.basename);
// if filtering, always hide the full completion achievement until it's unlocked
if ( filter && (ac.basename == "everything") && (ac.state.GetInt() <= 0) )
{
ac.Destroy();
continue;
}
if ( !ac.state ) ThrowAbortException("could not find cvar 'swwm_achievement_"..ac.basename.."'");
if ( ac.maxval )
{
ac.progress = CVar.FindCVar("swwm_progress_"..ac.basename);
if ( !ac.progress ) ThrowAbortException("could not find cvar 'swwm_progress_"..ac.basename.."'");
// special case for maxval
if ( ac.basename == "allcoll" )
{
int nc = 0;
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let c = (Class<SWWMCollectible>)(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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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<numpt; i++ )

View file

@ -618,7 +618,7 @@ Class Spreadgun : SWWMWeapon
s.vel += vel*.5+x*FRandom[Spreadgun](1.,20.)+y*FRandom[Spreadgun](-2,2)+z*FRandom[Spreadgun](-2,2);
}
SWWMUtility.DoKnockback(self,-x,30000.);
SWWMUtility.AchievementProgressInc('swwm_progress_golden',1,player);
SWWMUtility.AchievementProgressInc("golden",1,player);
break;
default:
st = new("SpreadgunTracer");

View file

@ -783,7 +783,7 @@ Class CorrodeDebuff : Inventory
// forcibly update
wasalive = true;
cnt = -1;
if ( instigator ) SWWMUtility.AchievementProgressInc('swwm_progress_acid',1,instigator.player);
if ( instigator ) SWWMUtility.AchievementProgressInc("acid",1,instigator.player);
}
override void DoEffect()
{
@ -1190,7 +1190,7 @@ Class TheBall : Actor
s.vel = pvel;
}
crit = true;
if ( target ) SWWMUtility.AchievementProgressInc('swwm_progress_balls',1,target.player);
if ( target ) SWWMUtility.AchievementProgressInc("balls",1,target.player);
}
SWWMUtility.DoKnockback(victim,vel.unit(),slamforce);
bool bleeds = (victim && !victim.bINVULNERABLE && !victim.bNOBLOOD && !victim.bDORMANT && is_schutt);
@ -1221,7 +1221,7 @@ Class TheBall : Actor
if ( crit )
SWWMUtility.DoExplosion(self,dmg/2,25000,150,80,ignoreme:target);
if ( crit && victim && (victim.Health <= 0) && victim.bBOSS && target )
SWWMUtility.MarkAchievement('swwm_achievement_clonk',target.player);
SWWMUtility.MarkAchievement("clonk",target.player);
// only rip shootables
if ( (slamforce > girth) && is_schutt )
{

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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