Major achievement progress.

This commit is contained in:
Mari the Deer 2021-03-24 02:25:38 +01:00
commit f5c9733c65
41 changed files with 868 additions and 276 deletions

View file

@ -142,6 +142,8 @@ 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
// cross-session achievement cvars (0: locked, 1: unlocked, 2: notified)
nosave int swwm_achievement_gcsandwich = 0;
nosave int swwm_achievement_hdoom = 0;
@ -226,6 +228,7 @@ nosave int swwm_achievement_snake = 0;
nosave int swwm_achievement_smb = 0;
nosave int swwm_achievement_tyrian = 0;
nosave int swwm_achievement_bof = 0;
nosave int swwm_achievement_wantdie = 0;
// cross-session progress cvars
nosave int swwm_progress_gcsandwich = 0;
nosave int swwm_progress_ghost = 0;
@ -240,7 +243,7 @@ nosave int swwm_progress_gib = 0;
nosave int swwm_progress_barrier = 0;
nosave int swwm_progress_bossdash = 0;
nosave int swwm_progress_sneeze = 0;
nosave int swwm_progress_fuel = 0;
nosave float swwm_progress_fuel = 0; // this one has to be a double
nosave int swwm_progress_slayer = 0;
nosave int swwm_progress_stomp = 0;
nosave int swwm_progress_thruwall = 0;
@ -257,7 +260,6 @@ nosave int swwm_progress_parry = 0;
nosave int swwm_progress_allkills = 0;
nosave int swwm_progress_allsecrets = 0;
nosave int swwm_progress_reflect = 0;
nosave int swwm_progress_wave = 0;
nosave int swwm_progress_friend = 0;
nosave int swwm_progress_shock = 0;
nosave int swwm_progress_balls = 0;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 B

After

Width:  |  Height:  |  Size: 189 B

Before After
Before After

View file

@ -854,7 +854,7 @@ 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_ONEGUY_TAG = "Fuck this Guy in Particular";
SWWM_ACHIEVEMENT_ONEGUY_TAG = "Fuck that Guy in Particular";
SWWM_ACHIEVEMENT_ONEGUY_TXT = "Use the Ynykron Artifact to kill a single non-boss enemy";
SWWM_ACHIEVEMENT_GOLDEN_TAG = "Golden Shower";
SWWM_ACHIEVEMENT_GOLDEN_TXT = "Use %d golden shells";
@ -897,9 +897,9 @@ SWWM_ACHIEVEMENT_BUSTIN_TXT = "Bust %d walls";
SWWM_ACHIEVEMENT_MOTH_TAG = "Mother";
SWWM_ACHIEVEMENT_MOTH_TXT = "Gather %d moths";
SWWM_ACHIEVEMENT_IWAD_TAG = "Mx. Worldwide";
SWWM_ACHIEVEMENT_IWAD_TXT = "Play on all supported IWADs";
SWWM_ACHIEVEMENT_IWAD_TXT = "Play on all supported games";
SWWM_ACHIEVEMENT_BRAKE_TAG = "No Brakes";
SWWM_ACHIEVEMENT_BRAKE_TXT = "Consume all your fuel while dashing %d times";
SWWM_ACHIEVEMENT_BRAKE_TXT = "Consume your full fuel supply in a single dash %d times";
SWWM_ACHIEVEMENT_RAGE_TAG = "No Talk me Angy";
SWWM_ACHIEVEMENT_RAGE_TXT = "Use %d Ragekits";
SWWM_ACHIEVEMENT_ABORT_TAG = "Oops I Broke It";
@ -915,7 +915,7 @@ SWWM_ACHIEVEMENT_REFLECT_TXT = "Kill %d enemies with parried projectiles";
SWWM_ACHIEVEMENT_SEKIRO_TAG = "Hesitation is Defeat";
SWWM_ACHIEVEMENT_SEKIRO_TXT = "Die and reboot two times in the same map";
SWWM_ACHIEVEMENT_WAVE_TAG = "Sayonara, Scumbag";
SWWM_ACHIEVEMENT_WAVE_TXT = "Wave at a dying enemy %d times";
SWWM_ACHIEVEMENT_WAVE_TXT = "Wave at a dying enemy";
SWWM_ACHIEVEMENT_FRIEND_TAG = "Shaped like a Friend";
SWWM_ACHIEVEMENT_FRIEND_TXT = "Befriend %d Cacodemons, Weredragons or Ettins with headpats";
SWWM_ACHIEVEMENT_SHOCK_TAG = "Shockmaster";
@ -941,13 +941,13 @@ SWWM_ACHIEVEMENT_DOSH_TXT = "Have ¥1,000,000,000 in bank";
SWWM_ACHIEVEMENT_JUMP_TAG = "Verticality";
SWWM_ACHIEVEMENT_JUMP_TXT = "Walljump %d times";
SWWM_ACHIEVEMENT_EZKILL_TAG = "Well That was Easy";
SWWM_ACHIEVEMENT_EZKILL_TXT = "Kill %d enemies with a single Ynykron Artifact shot";
SWWM_ACHIEVEMENT_EZKILL_TXT = "Kill %d enemies with a single Ynykron Artifact shot (excluding altfire)";
SWWM_ACHIEVEMENT_LIGMA_TAG = "Who's Steve Jobs?";
SWWM_ACHIEVEMENT_LIGMA_TXT = "Kill an endgame boss with the Ynykron Artifact";
SWWM_ACHIEVEMENT_YEET_TAG = "YEET";
SWWM_ACHIEVEMENT_YEET_TXT = "Throw a Candygun right into the Icon of Sin's brains";
SWWM_ACHIEVEMENT_MBF_TAG = "You can Pet the Dog";
SWWM_ACHIEVEMENT_MBF_TXT = "Pet an MBF Helper Dog";
SWWM_ACHIEVEMENT_MBF_TXT = "Pet a dog";
SWWM_ACHIEVEMENT_LIGHTNING_TAG = "And the Dragons were No More";
SWWM_ACHIEVEMENT_LIGHTNING_TXT = "Kill the Death Wyvern using the Rail Carbine";
SWWM_ACHIEVEMENT_DAKKA_TAG = "Dakka";
@ -994,3 +994,5 @@ SWWM_ACHIEVEMENT_TYRIAN_TAG = "Master of SHMUPs";
SWWM_ACHIEVEMENT_TYRIAN_TXT = "Complete a full game of Interstellar Demolitionist";
SWWM_ACHIEVEMENT_BOF_TAG = "Master of RPGs";
SWWM_ACHIEVEMENT_BOF_TXT = "Complete a full game of Demolition Quest";
SWWM_ACHIEVEMENT_WANTDIE_TAG = "E N D M I I";
SWWM_ACHIEVEMENT_WANTDIE_TXT = "Fully clear a single map in the hardest difficulty (without dying)";

View file

@ -756,7 +756,7 @@ 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_ONEGUY_TAG = "A la Mierda este Tío en Particular";
SWWM_ACHIEVEMENT_ONEGUY_TAG = "A la Mierda el Tío Ese";
SWWM_ACHIEVEMENT_ONEGUY_TXT = "Usa el Artefacto Ynykron para matar a un único enemigo no-jefe";
SWWM_ACHIEVEMENT_GOLDEN_TAG = "Lluvia Dorada";
SWWM_ACHIEVEMENT_GOLDEN_TXT = "Usa %d cartuchos dorados";
@ -797,9 +797,9 @@ SWWM_ACHIEVEMENT_BUSTIN_TAG = "Me Hace Sentir Bien";
SWWM_ACHIEVEMENT_BUSTIN_TXT = "Revienta %d paredes";
SWWM_ACHIEVEMENT_MOTH_TAG = "Madre Polilla";
SWWM_ACHIEVEMENT_MOTH_TXT = "Reúne %d polillas";
SWWM_ACHIEVEMENT_IWAD_TXT = "Juega en todos los IWADs soportados";
SWWM_ACHIEVEMENT_IWAD_TXT = "Juega en todos los juegos soportados";
SWWM_ACHIEVEMENT_BRAKE_TAG = "Sin Frenos";
SWWM_ACHIEVEMENT_BRAKE_TXT = "Consume todo tu combustible esprintando %d veces";
SWWM_ACHIEVEMENT_BRAKE_TXT = "Consume toda tu capacidad de combustible en un solo esprint %d veces";
SWWM_ACHIEVEMENT_RAGE_TAG = "No Hablo me Enfado";
SWWM_ACHIEVEMENT_RAGE_TXT = "Usa %d Ragekits";
SWWM_ACHIEVEMENT_ABORT_TAG = "Uy lo He Roto";
@ -815,7 +815,7 @@ SWWM_ACHIEVEMENT_REFLECT_TXT = "Mata %d enemigos con proyectiles desviados";
SWWM_ACHIEVEMENT_SEKIRO_TAG = "Dudar es Fracasar";
SWWM_ACHIEVEMENT_SEKIRO_TXT = "Muere y reinicia dos veces en el mismo mapa";
SWWM_ACHIEVEMENT_WAVE_TAG = "Sayonara, Capullo";
SWWM_ACHIEVEMENT_WAVE_TXT = "Saluda a un enemigo muriéndose %d veces";
SWWM_ACHIEVEMENT_WAVE_TXT = "Saluda a un enemigo muriéndose";
SWWM_ACHIEVEMENT_FRIEND_TAG = "Con Forma de Amigo";
SWWM_ACHIEVEMENT_FRIEND_TXT = "Entabla amistad con %d Cacodemonios, Hombres-Dragón o Ettins a base de caricias";
SWWM_ACHIEVEMENT_SHOCK_TXT = "Realiza %d combos de Biospark";
@ -839,12 +839,12 @@ SWWM_ACHIEVEMENT_DOSH_TXT = "Ten ¥1.000.000.000 en mano";
SWWM_ACHIEVEMENT_JUMP_TAG = "Verticalidad";
SWWM_ACHIEVEMENT_JUMP_TXT = "Salta paredes %d veces";
SWWM_ACHIEVEMENT_EZKILL_TAG = "Eso Estuvo Fácil";
SWWM_ACHIEVEMENT_EZKILL_TXT = "Mata %d enemigos con un solo disparo de Artefacto Ynykron";
SWWM_ACHIEVEMENT_EZKILL_TXT = "Mata %d enemigos con un solo disparo de Artefacto Ynykron (excluyendo modo secundario)";
SWWM_ACHIEVEMENT_LIGMA_TAG = "¿Quien es Steve Jobs?";
SWWM_ACHIEVEMENT_LIGMA_TXT = "Mata a un jefe final con el Artefacto Ynykron";
SWWM_ACHIEVEMENT_YEET_TXT = "Lanza una Pistola Caramelo justo dentro del cerebro del Icono del Pecado";
SWWM_ACHIEVEMENT_MBF_TAG = "Puedes Acariciar el Perro";
SWWM_ACHIEVEMENT_MBF_TXT = "Acaricia un Perro Ayudante MBF";
SWWM_ACHIEVEMENT_MBF_TXT = "Acaricia un perro";
SWWM_ACHIEVEMENT_LIGHTNING_TAG = "Y los Dragones Desaparecieron";
SWWM_ACHIEVEMENT_LIGHTNING_TXT = "Mata al Wyvern Mortal usando la Carabina de Raíl";
SWWM_ACHIEVEMENT_DAKKA_TXT = "Dispara la Ametralladora Sheen durante un minuto entero";
@ -888,3 +888,5 @@ SWWM_ACHIEVEMENT_TYRIAN_TAG = "Maestro de SHMUPs";
SWWM_ACHIEVEMENT_TYRIAN_TXT = "Completa una partida entera de Interstellar Demolitionist";
SWWM_ACHIEVEMENT_BOF_TAG = "Maestro de RPGs";
SWWM_ACHIEVEMENT_BOF_TXT = "Completa una partida entera de Demolition Quest";
SWWM_ACHIEVEMENT_WANTDIE_TAG = "Mata a tu Jefe";
SWWM_ACHIEVEMENT_WANTDIE_TXT = "Despeja un mapa en la dificultad más alta (sin morir)";

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r395 \cu(Tue 23 Mar 17:03:51 CET 2021)\c-";
SWWM_SHORTVER="\cw0.9.11b-pre r395 \cu(2021-03-23 17:03:51)\c-";
SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.11b-pre r396 \cu(Wed 24 Mar 02:25:38 CET 2021)\c-";
SWWM_SHORTVER="\cw0.9.11b-pre r396 \cu(2021-03-24 02:25:38)\c-";

View file

@ -34,6 +34,7 @@ Class SWWMHDoomHandler : StaticEventHandler
"\cx┃ \cfIf you want Demo-chan to actually fuck some hot demon girls, \cx┃\n"
"\cx┃ \cfjust go commission a porn artist or something, idk. \cx┃\n"
"\cx┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛");
SWWMUtility.MarkAchievement('swwm_achievement_hdoom',players[consoleplayer]);
}
override void WorldLoaded( WorldEvent e )

View file

@ -39,6 +39,7 @@ Class SWWMBrutalHandler : StaticEventHandler
"\cx┃ \cfand trust me, it's better this way. \cx┃\n"
"\cx┃ \cf<See you again, have a nice day> \cx┃\n"
"\cx┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛");
SWWMUtility.MarkAchievement('swwm_achievement_broccolidoccoli',players[consoleplayer]);
}
override void WorldLoaded( WorldEvent e )

View file

@ -19,6 +19,7 @@ extend Class SWWMHandler
S_StartSound("menu/buyinv",CHAN_ITEM,CHANF_UI);
S_StartSound("misc/emone",CHAN_VOICE,CHANF_UI);
}
SWWMCredits.HasCheated(players[e.Args[0]]);
SWWMCredits.Give(players[e.Args[0]],1000000000);
SWWMScoreObj.Spawn(1000000000,players[e.Args[0]].mo.Vec3Offset(0,0,players[e.Args[0]].mo.Height/2));
}
@ -341,6 +342,7 @@ extend Class SWWMHandler
if ( kstr != cht[i].Left(kstr.length()) ) continue;
matchany = true;
if ( kstr != cht[i] ) continue;
if ( i > 4 ) SWWMUtility.MarkAchievement('swwm_achievement_cheat',players[consoleplayer]);
if ( SWWMUtility.CheatsDisabled(consoleplayer) )
{
kfail = true;

View file

@ -101,6 +101,7 @@ extend Class SWWMHandler
s.AddDamageDealt(e.Damage);
if ( e.Damage > s.topdealt ) s.topdealt = e.Damage;
}
SWWMFlyTracker.Track(e.Thing,e.DamageSource);
}
}
@ -156,6 +157,25 @@ extend Class SWWMHandler
lastcombat = AddOneliner("scorekill",1,15);
}
}
// achievement stuff
if ( e.Thing.IsHostile(src) )
{
if ( e.Thing.bBOSS && ((e.DamageType == 'Dash') || (e.DamageType == 'Buttslam')) )
SWWMUtility.AchievementProgressInc('swwm_progress_bossdash',1,src.player);
if ( e.DamageType == 'Push' )
SWWMUtility.AchievementProgressInc('swwm_progress_sneeze',1,src.player);
else if ( e.DamageType == 'Buttslam' )
SWWMUtility.AchievementProgressInc('swwm_progress_butts',1,src.player);
else if ( e.DamageType == 'Jump' )
SWWMUtility.AchievementProgressInc('swwm_progress_stomp',1,src.player);
else if ( e.DamageType == 'GroundPound' )
SWWMUtility.AchievementProgressInc('swwm_progress_thicc',1,src.player);
else if ( (e.DamageType == 'Love') && !(e.Thing is 'WolfensteinSS') )
SWWMUtility.AchievementProgressInc('swwm_progress_love',1,src.player);
if ( e.Inflictor && e.Inflictor.FindInventory('ParriedBuff') )
SWWMUtility.AchievementProgressInc('swwm_progress_reflect',1,src.player);
SWWMUtility.AchievementProgressInc('swwm_progress_mega',1,src.player);
}
// no credits unless it's a counted kill or marine (that isn't friendly)
if ( e.Thing.IsFriend(src) || (!e.Thing.default.bCountKill && !(e.Thing is 'ScriptedMarine')) )
return;
@ -236,6 +256,7 @@ extend Class SWWMHandler
scr.xstr[ofs] = StringTable.Localize("$SWWM_OVERKILL");
scr.xcnt = ++ofs;
}
SWWMUtility.AchievementProgressInc('swwm_progress_gib',1,src.player);
}
score = int(score*(1.+.5*min(multilevel[pnum],16)));
if ( (multilevel[pnum] > 0) && scr )
@ -281,6 +302,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);
}
}

View file

@ -1,5 +1,7 @@
// vanilla boss stuff
Class EndgameBossMarker : Inventory {}
extend Class SWWMHandler
{
String bosstag;
@ -131,6 +133,7 @@ extend Class SWWMHandler
bossactors.Push(e.Thing);
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 6;
if ( trk ) trk.bBOSS = true;
e.Thing.GiveInventory('EndgameBossMarker',1);
}
bosstag = "$BT_SPIDER";
}
@ -162,6 +165,7 @@ extend Class SWWMHandler
bossactors.Push(e.Thing);
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 40; // goodbye, instakills
if ( trk ) trk.bBOSS = true;
e.Thing.GiveInventory('EndgameBossMarker',1);
}
if ( e.Thing is 'BossEye' )
bossviewactor = e.Thing;
@ -195,6 +199,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 2;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_DSPARIL";
e.Thing.GiveInventory('EndgameBossMarker',1);
}
else if ( e.Thing is 'Sorcerer2' )
{
@ -205,6 +210,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 8;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_DSPARIL2";
e.Thing.GiveInventory('EndgameBossMarker',1);
}
}
else if ( bossmap == MAP_HMAP38 )
@ -265,6 +271,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 10;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_KORAX";
e.Thing.GiveInventory('EndgameBossMarker',1);
}
}
else if ( bossmap == MAP_HMAP60 )
@ -276,6 +283,7 @@ extend Class SWWMHandler
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_DEATHKINGS";
initialized = true; // healthbar shows from the start
e.Thing.GiveInventory('EndgameBossMarker',1);
}
}
else if ( bossmap == MAP_EVMAP30 )
@ -286,6 +294,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 5;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_ARCHANGELUS";
e.Thing.GiveInventory('EndgameBossMarker',1);
}
else if ( e.Thing.GetClassName() == "ArchangelusB" )
{
@ -296,6 +305,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 5;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_ARCHANGELUS";
e.Thing.GiveInventory('EndgameBossMarker',1);
}
}
}

View file

@ -9,6 +9,8 @@ extend Class SWWMHandler
// for minimap
Array<int> ffsectors;
Array<Key> mapkeys;
// level end stats
override void WorldUnloaded( WorldEvent e )
{
@ -70,6 +72,21 @@ extend Class SWWMHandler
players[i].mo.GiveInventory("InventoryWipeToken",1);
}
}
// did we complete this map without collecting any of its keys? (doesn't work for hubs)
if ( (mapkeys.Size() > 0) && !(level.clusterflags&LevelLocals.CLUSTER_HUB) )
{
bool collected = false;
for ( int i=0; i<mapkeys.Size(); i++ )
{
if ( !mapkeys[i].Owner || !mapkeys[i].Owner.player ) continue;
collected = true;
break;
}
if ( !collected ) SWWMUtility.MarkAchievement('swwm_achievement_cliffyb',players[consoleplayer]);
}
// beat the par time?
if ( level.partime && (Thinker.Tics2Seconds(level.maptime) <= level.partime) )
SWWMUtility.AchievementProgressInc('swwm_progress_par',1,players[consoleplayer]);
}
private void SetupLockdefsCache( SWWMCachedLockInfo cli )
@ -249,5 +266,13 @@ extend Class SWWMHandler
}
// spawn loot
Chancebox.SpawnChanceboxes();
// list map keys
let ti = ThinkerIterator.Create("Key");
Key k;
while ( k = Key(ti.Next()) )
{
if ( k.Owner ) continue;
mapkeys.Push(k);
}
}
}

View file

@ -55,6 +55,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]);
}
SWWMCredits.Give(players[i],score);
SWWMScoreObj.Spawn(score,players[i].mo.Vec3Offset(0,0,players[i].mo.Height/2));
@ -189,6 +190,15 @@ extend Class SWWMHandler
}
}
mapclearagain++;
if ( !iwantdie ) return;
let ti = ThinkerIterator.Create("SWWMStats",Thinker.STAT_STATIC);
SWWMStats s;
while ( s = SWWMStats(ti.Next()) )
{
if ( s.deaths > 0 )
return;
}
SWWMUtility.MarkAchievement('swwm_achievement_wantdie',players[consoleplayer]);
}
// "simple" tracking (used by the minimap)

View file

@ -1,56 +1,55 @@
// 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_GCSANDWICH = 25;
const SA_GHOST = 25;
const SA_ALLITEMS = 30;
const SA_CONGA = 15;
const SA_EXPLOGUN = 7;
const SA_GRAVITY = 25;
const SA_FLIGHT = 2000;
const SA_PAR = 30;
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_BARRIER = 25;
const SA_BOSSDASH = 10;
const SA_SNEEZE = 20;
const SA_FUEL = 400;
const SA_SLAYER = 40;
const SA_STOMP = 50;
const SA_THRUWALL = 30;
const SA_THRUWALL = 25;
const SA_LEAD = 1500;
const SA_LOVE = 50;
const SA_LOVE = 20;
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_MOTH = 50;
const SA_BRAKE = 20;
const SA_RAGE = 25;
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_ALLKILLS = 30;
const SA_ALLSECRETS = 30;
const SA_REFLECT = 20;
const SA_FRIEND = 30;
const SA_SHOCK = 30;
const SA_BALLS = 10;
const SA_REFRESH = 25;
const SA_STEP = 60;
const SA_SUNNY = 30;
const SA_SUNNY = 25;
const SA_THICC = 80;
const SA_SLEMG = 100;
const SA_JUMP = 100;
const SA_EZKILL = 200;
const SA_SLEMG = 50;
const SA_JUMP = 80;
const SA_EZKILL = 100;
const SA_ROAST = 30;
const SA_DAB = 60;
const SA_DAB = 100;
const SA_HND = 6;
const SA_GEPGUN = 50;
const SA_GEPGUN = 30;
const SA_PENE = 20;
const SA_ACID = 200;
const SA_ACID = 100;
const SA_SANIC = 800;
const SA_BUNE = 150;
const SA_BONK = 300;
const SA_ANOM = 40;
const SA_ANOM = 25;
// achievement unlock tracking
extend Class SWWMStaticHandler
@ -84,6 +83,7 @@ extend Class SWWMStaticHandler
else if ( ac == 'swwm_achievement_dakka' ) maxval = 60;
else if ( ac == 'swwm_achievement_dosh' ) maxval = 1000000000;
else if ( ac == 'swwm_achievement_mega' ) maxval = 1000000;
else if ( ac == 'swwm_achievement_iwad' ) maxval = 7;
if ( val && (prog < maxval) )
{
ev.SetInt(0);
@ -194,7 +194,8 @@ extend Class SWWMStaticHandler
'swwm_achievement_snake',
'swwm_achievement_smb',
'swwm_achievement_tyrian',
'swwm_achievement_bof'
'swwm_achievement_bof',
'swwm_achievement_wantdie'
};
// localized name
static const String names[] =
@ -280,7 +281,8 @@ extend Class SWWMStaticHandler
"$SWWM_ACHIEVEMENT_SNAKE",
"$SWWM_ACHIEVEMENT_SMB",
"$SWWM_ACHIEVEMENT_TYRIAN",
"$SWWM_ACHIEVEMENT_BOF"
"$SWWM_ACHIEVEMENT_BOF",
"$SWWM_ACHIEVEMENT_WANTDIE"
};
// has number in txt
static const int number[] =
@ -328,7 +330,7 @@ extend Class SWWMStaticHandler
SA_ALLSECRETS,
SA_REFLECT,
0, // SEKIRO
SA_WAVE,
0, // WAVE
SA_FRIEND,
SA_SHOCK,
SA_BALLS,
@ -366,7 +368,8 @@ extend Class SWWMStaticHandler
0, // SNAKE
0, // SMB
0, // TYRIAN
0 // BOF
0, // BOF
0 // WANTDIE
};
// is ignored (hide away achievements that can't be done yet)
static const bool ignoreme[] =
@ -452,93 +455,95 @@ extend Class SWWMStaticHandler
true, // SNAKE
true, // SMB
true, // TYRIAN
true // BOF
true, // BOF
false // WANTDIE
};
// progress tracking cvar (if any)
static const Name pvar[] =
{
'swwm_progress_gcsandwich', // GCSANDWICH
'swwm_progress_gcsandwich',
'None', // HDOOM
'None', // ONESTANDING
'None', // OOPSIE
'swwm_progress_ghost', // GHOST
'swwm_progress_ghost',
'None', // CLONK
'swwm_progress_allitems', // ALLITEMS
'swwm_progress_conga', // CONGA
'swwm_progress_explogun', // EXPLOGUN
'swwm_progress_gravity', // GRAVITY
'swwm_progress_flight', // FLIGHT
'swwm_progress_allitems',
'swwm_progress_conga',
'swwm_progress_explogun',
'swwm_progress_gravity',
'swwm_progress_flight',
'None', // CLIFFYB
'swwm_progress_par', // PAR
'swwm_progress_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
'swwm_progress_golden',
'swwm_progress_gib',
'swwm_progress_barrier',
'swwm_progress_bossdash',
'swwm_progress_sneeze',
'swwm_progress_fuel',
'swwm_progress_slayer',
'None', // BROCCOLIDOCCOLI
'None', // DIME
'swwm_progress_stomp', // STOMP
'swwm_progress_stomp',
'None', // CHEAT
'None', // GOD
'swwm_progress_thruwall', // THRUWALL
'swwm_progress_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_lead',
'swwm_progress_love',
'swwm_progress_butts',
'swwm_progress_plush',
'swwm_progress_bustin',
'swwm_progress_moth',
'swwm_progress_iwad',
'swwm_progress_brake', // BRAKE
'swwm_progress_rage', // RAGE
'swwm_progress_rage',
'None', // ABORT
'swwm_progress_parry', // PARRY
'swwm_progress_allkills', // ALLKILLS
'swwm_progress_allsecrets', // ALLSECRETS
'swwm_progress_reflect', // REFLECT
'swwm_progress_parry',
'swwm_progress_allkills',
'swwm_progress_allsecrets',
'swwm_progress_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', // WAVE
'swwm_progress_friend',
'swwm_progress_shock',
'swwm_progress_balls',
'swwm_progress_refresh',
'swwm_progress_step',
'swwm_progress_sunny',
'swwm_progress_thicc',
'swwm_progress_allcoll',
'swwm_progress_slemg',
'swwm_progress_dosh',
'swwm_progress_jump',
'swwm_progress_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
'swwm_progress_dakka',
'swwm_progress_roast',
'swwm_progress_dab',
'swwm_progress_hnd',
'swwm_progress_gepgun',
'None', // FULLER
'swwm_progress_pene', // PENE
'swwm_progress_acid', // ACID
'swwm_progress_pene',
'swwm_progress_acid',
'None', // SALT
'swwm_progress_mega', // MEGA
'swwm_progress_sanic', // SANIC
'swwm_progress_mega',
'swwm_progress_sanic',
'None', // TELE
'swwm_progress_bune', // BUNE
'swwm_progress_bonk', // BONK
'swwm_progress_anom', // ANOM
'swwm_progress_bune',
'swwm_progress_bonk',
'swwm_progress_anom',
'None', // ANONE
'None', // TETRIS
'None', // PONG
'None', // SNAKE
'None', // SMB
'None', // TYRIAN
'None' // BOF
'None', // BOF
'None' // WANTDIE
};
bool alldone = true;
for ( int i=0; i<vars.Size(); i++ )

View file

@ -206,10 +206,10 @@ Class SWWMAchievementNotification : HUDMessageBase
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));
Vector2 pos = (int(ss.x-256)/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);
BrokenLines l = fnt2.BreakLines(loctxt,200);
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);
@ -218,7 +218,7 @@ Class SWWMAchievementNotification : HUDMessageBase
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);
Screen.DrawText(fnt2,Font.CR_WHITE,pos.x+44,pos.y+yy,l.StringAt(i),DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true,DTA_Alpha,alpha);
yy += 9;
}
}

View file

@ -80,6 +80,26 @@ Class SWWMCollectible : Inventory abstract
override void AttachToOwner( Actor other )
{
Super.AttachToOwner(other);
// count how many we have, set progress accordingly
int nc = 0, tnc = 0, cnc = 0;
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let c = (Class<SWWMCollectible>)(AllActorClasses[i]);
if ( !c || (c == 'SWWMCollectible') ) continue;
let def = GetDefaultByType(c);
tnc++;
// check that we can collect it in this IWAD
if ( !def.ValidGame() ) continue;
nc++;
}
for ( Inventory i=other.inv; i; i=i.inv )
{
if ( i is 'SWWMCollectible' )
cnc++;
}
// force progress to be "total collectibles" so this doesn't get unset on other IWADs that may have more
if ( cnc == nc ) SWWMUtility.AchievementProgress('swwm_progress_allcoll',tnc,other.player);
else SWWMUtility.AchievementProgress('swwm_progress_allcoll',cnc,other.player);
// we're only attaching to the other players
if ( propagated )
return;

View file

@ -100,11 +100,19 @@ Class SayaBeanGesture : SWWMItemGesture
}
A_StartSound("saya/giggle",CHAN_ITEMEXTRA,CHANF_OVERLAP);
}
action void A_UsePlush()
{
if ( !Demolitionist(self) ) return;
let s = Demolitionist(self).mystats;
if ( !s ) return;
s.plushuses++;
SWWMUtility.AchievementProgress('swwm_progress_plush',s.plushuses,player);
}
States
{
Fire:
XZW1 A 3;
XZW1 A 3 A_UsePlush();
XZW1 B 3 A_StartSound("demolitionist/handsup",CHAN_WEAPON,CHANF_OVERLAP);
XZW1 CDEFGH 3;
XZW1 IJ 4;

View file

@ -183,6 +183,7 @@ Class RefresherItem : SWWMHealth
}
override void AutoUseExtra( bool recursive )
{
SWWMUtility.AchievementProgressInc('swwm_progress_refresh',1,Owner.player);
// regen effect doesn't stack if we autoactivated recursively
if ( recursive ) return;
let p = Powerup(Owner.FindInventory("RefresherRegen"));

View file

@ -26,6 +26,7 @@ Class GrilledCheeseSandwich : Inventory
double lastsafeangle[5];
int safetic;
int dteleport;
Actor lastdropper;
override Inventory CreateCopy( Actor other )
{
@ -35,6 +36,7 @@ Class GrilledCheeseSandwich : Inventory
}
void DoTheThing( bool extrasafe = false )
{
SWWMUtility.AchievementProgressInc('swwm_progress_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);
@ -183,9 +185,14 @@ Class GrilledCheeseSandwich : Inventory
other.Inv = Inv;
Inv = saved;
}
override void OnDrop( Actor dropper )
{
lastdropper = dropper;
}
override void PostTeleport( Vector3 destpos, double destangle, int flags )
{
// TODO "teleported bread" achievement
if ( !lastdropper ) return;
SWWMUtility.MarkAchievement('swwm_achievement_tele',lastdropper.player);
}
Default
@ -392,6 +399,7 @@ Class GhostArtifact : Inventory
Demolitionist(Owner).lastbump *= 1.04;
}
else Owner.GiveInventory("GhostPower",1);
SWWMUtility.AchievementProgressInc('swwm_progress_ghost',1,Owner.player);
return true;
}
@ -541,6 +549,7 @@ Class GravitySuppressor : Inventory
Demolitionist(Owner).lastbump *= 1.04;
}
else Owner.GiveInventory("GravityPower",1);
SWWMUtility.AchievementProgressInc('swwm_progress_gravity',1,Owner.player);
return true;
}
override void Travelled()
@ -782,6 +791,7 @@ Class FuckingInvinciball : Inventory
Demolitionist(Owner).lastbump *= 1.1;
}
else Owner.GiveInventory("InvinciballPower",1);
SWWMUtility.AchievementProgressInc('swwm_progress_sunny',1,Owner.player);
return true;
}
override void Travelled()
@ -1064,6 +1074,7 @@ Class Ragekit : Inventory
Demolitionist(Owner).lastbump *= .95;
}
else Owner.GiveInventory("RagekitPower",1);
SWWMUtility.AchievementProgressInc('swwm_progress_rage',1,Owner.player);
return true;
}
override void Travelled()
@ -1560,6 +1571,7 @@ Class CompanionLamp : Actor
m.lamp = self;
m.trail = m.pos;
moff.Push(m);
SWWMUtility.AchievementProgressInc('swwm_progress_moth',1,parent.player);
}
override void PostBeginPlay()
{
@ -2015,6 +2027,7 @@ Class EBarrier : Inventory
Demolitionist(Owner).lastbump *= 0.95;
}
else Owner.GiveInventory("BarrierPower",1);
SWWMUtility.AchievementProgressInc('swwm_progress_barrier',1,Owner.player);
return true;
}
override void Travelled()
@ -2628,12 +2641,15 @@ Class Mykradvo : Inventory
Amount++;
return true;
}
if ( (targets.Size() == 1) && targets[0] && !targets[0].bBOSS )
SWWMUtility.MarkAchievement('swwm_achievement_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);
return true;
}

View file

@ -437,7 +437,8 @@ Class DemolitionistMenu : GenericMenu
'swwm_achievement_snake',
'swwm_achievement_smb',
'swwm_achievement_tyrian',
'swwm_achievement_bof'
'swwm_achievement_bof',
'swwm_achievement_wantdie'
};
// localized name
static const String names[] =
@ -524,7 +525,8 @@ Class DemolitionistMenu : GenericMenu
"$SWWM_ACHIEVEMENT_SNAKE",
"$SWWM_ACHIEVEMENT_SMB",
"$SWWM_ACHIEVEMENT_TYRIAN",
"$SWWM_ACHIEVEMENT_BOF"
"$SWWM_ACHIEVEMENT_BOF",
"$SWWM_ACHIEVEMENT_WANTDIE"
};
// has number in txt
static const int number[] =
@ -572,7 +574,7 @@ Class DemolitionistMenu : GenericMenu
SA_ALLSECRETS,
SA_REFLECT,
0, // SEKIRO
SA_WAVE,
0, // WAVE
SA_FRIEND,
SA_SHOCK,
SA_BALLS,
@ -611,7 +613,8 @@ Class DemolitionistMenu : GenericMenu
0, // SNAKE
0, // SMB
0, // TYRIAN
0 // BOF
0, // BOF
0 // WANTDIE
};
// is ignored (hide away achievements that can't be done yet)
static const bool ignoreme[] =
@ -698,94 +701,96 @@ Class DemolitionistMenu : GenericMenu
true, // SNAKE
true, // SMB
true, // TYRIAN
true // BOF
true, // BOF
false // WANTDIE
};
// progress tracking cvar (if any)
static const Name pvar[] =
{
'swwm_progress_gcsandwich', // GCSANDWICH
'swwm_progress_gcsandwich',
'None', // HDOOM
'None', // ONESTANDING
'None', // OOPSIE
'swwm_progress_ghost', // GHOST
'swwm_progress_ghost',
'None', // CLONK
'swwm_progress_allitems', // ALLITEMS
'swwm_progress_conga', // CONGA
'swwm_progress_explogun', // EXPLOGUN
'swwm_progress_gravity', // GRAVITY
'swwm_progress_flight', // FLIGHT
'swwm_progress_allitems',
'swwm_progress_conga',
'swwm_progress_explogun',
'swwm_progress_gravity',
'swwm_progress_flight',
'None', // CLIFFYB
'swwm_progress_par', // PAR
'swwm_progress_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
'swwm_progress_golden',
'swwm_progress_gib',
'swwm_progress_barrier',
'swwm_progress_bossdash',
'swwm_progress_sneeze',
'swwm_progress_fuel',
'swwm_progress_slayer',
'None', // BROCCOLIDOCCOLI
'None', // DIME
'swwm_progress_stomp', // STOMP
'swwm_progress_stomp',
'None', // CHEAT
'None', // GOD
'swwm_progress_thruwall', // THRUWALL
'swwm_progress_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
'swwm_progress_lead',
'swwm_progress_love',
'swwm_progress_butts',
'swwm_progress_plush',
'swwm_progress_bustin',
'swwm_progress_moth',
'swwm_progress_iwad',
'swwm_progress_brake',
'swwm_progress_rage',
'None', // ABORT
'swwm_progress_parry', // PARRY
'swwm_progress_allkills', // ALLKILLS
'swwm_progress_allsecrets', // ALLSECRETS
'swwm_progress_reflect', // REFLECT
'swwm_progress_parry',
'swwm_progress_allkills',
'swwm_progress_allsecrets',
'swwm_progress_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', // WAVE
'swwm_progress_friend',
'swwm_progress_shock',
'swwm_progress_balls',
'swwm_progress_refresh',
'swwm_progress_step',
'swwm_progress_sunny',
'swwm_progress_thicc',
'None', // EVERYTHING
'swwm_progress_allcoll', // ALLCOLL
'swwm_progress_slemg', // SLEMG
'swwm_progress_dosh', // DOSH
'swwm_progress_jump', // JUMP
'swwm_progress_ezkill', // EZKILL
'swwm_progress_allcoll',
'swwm_progress_slemg',
'swwm_progress_dosh',
'swwm_progress_jump',
'swwm_progress_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
'swwm_progress_dakka',
'swwm_progress_roast',
'swwm_progress_dab',
'swwm_progress_hnd',
'swwm_progress_gepgun',
'None', // FULLER
'swwm_progress_pene', // PENE
'swwm_progress_acid', // ACID
'swwm_progress_pene',
'swwm_progress_acid',
'None', // SALT
'swwm_progress_mega', // MEGA
'swwm_progress_sanic', // SANIC
'swwm_progress_mega',
'swwm_progress_sanic',
'None', // TELE
'swwm_progress_bune', // BUNE
'swwm_progress_bonk', // BONK
'swwm_progress_anom', // ANOM
'swwm_progress_bune',
'swwm_progress_bonk',
'swwm_progress_anom',
'None', // ANONE
'None', // TETRIS
'None', // PONG
'None', // SNAKE
'None', // SMB
'None', // TYRIAN
'None' // BOF
'None', // BOF
'None' // WANTDIE
};
achievements.Clear();
for ( int i=0; i<vars.Size(); i++ )
@ -817,6 +822,7 @@ Class DemolitionistMenu : GenericMenu
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;
else if ( vars[i] == 'swwm_achievement_iwad' ) ac.maxval = 7;
achievements.Push(ac);
}
AchievementUnknown = TexMan.CheckForTexture("graphics/Achievements/AchievementUnknown.png",TexMan.Type_Any);
@ -2662,13 +2668,33 @@ Class DemolitionistMenu : GenericMenu
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);
int val = a.progress.GetInt();
int mval = a.maxval;
if ( a.tag == "$SWWM_ACHIEVEMENT_IWAD_TAG" )
{
// special case
mval = 3;
int bits = val;
val = 0;
for ( int i=0; i<3; i++ ) if ( bits&(1<<i) ) val++;
}
int cur = min(val,mval);
afactor = cur/double(mval);
}
if ( b.progress )
{
int cur = min(b.progress.GetInt(),b.maxval);
bfactor = cur/double(b.maxval);
int val = b.progress.GetInt();
int mval = b.maxval;
if ( b.tag == "$SWWM_ACHIEVEMENT_IWAD_TAG" )
{
// special case
mval = 3;
int bits = val;
val = 0;
for ( int i=0; i<3; i++ ) if ( bits&(1<<i) ) val++;
}
int cur = min(val,mval);
bfactor = cur/double(mval);
}
if ( adone && bdone )
{
@ -3054,7 +3080,7 @@ Class DemolitionistMenu : GenericMenu
statlist.Push(str);
str = String.Format("\cx%s\c-%d",StringTable.Localize("$SWWM_STATSTOMP"),stats.stompcount);
statlist.Push(str);
str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATFUEL"),stats.fuelusage/60.,StringTable.Localize("$SWWM_UNIT_LITER"));
str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATFUEL"),stats.fuelusage,StringTable.Localize("$SWWM_UNIT_LITER"));
statlist.Push(str);
str = String.Format("\cx%s\c-%g\cu%s\c-",StringTable.Localize("$SWWM_STATSPEED"),(stats.topspeed*3600.*GameTicRate)/32000.,StringTable.Localize("$SWWM_UNIT_KPH"));
statlist.Push(str);
@ -3614,17 +3640,28 @@ Class DemolitionistMenu : GenericMenu
// 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);
int val = a.progress.GetInt();
int mval = a.maxval;
if ( a.tag == "$SWWM_ACHIEVEMENT_IWAD_TAG" )
{
// special case
mval = 3;
int bits = val;
val = 0;
for ( int i=0; i<3; i++ ) if ( bits&(1<<i) ) val++;
}
val = clamp(val,0,mval);
if ( completed ) str = SWWMUtility.BlockBar(mval,mval,barsz,Font.CR_DARKGREEN,Font.CR_BLACK);
else str = SWWMUtility.BlockBar(val,mval,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));
if ( completed ) str = String.Format("%s / %s",SWWMUtility.ThousandsNum(mval),SWWMUtility.ThousandsNum(mval));
else str = String.Format("%s / %s",SWWMUtility.ThousandsNum(val),SWWMUtility.ThousandsNum(mval));
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);
Screen.DrawText(MiniwiFont,completed?Font.CR_GREEN:hasprogress?Font.CR_WHITE:Font.CR_DARKGRAY,origin.x+xx+ox,origin.y+yy+37,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);
str = SWWMUtility.BlockBar(completed,1,barsz,Font.CR_DARKGREEN,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

View file

@ -56,6 +56,25 @@ Class SWWMGesture : SWWMWeapon
if ( !psp ) return;
if ( (Owner.Health <= 0) && (psp.CurState != ResolveState("Deselect")) )
Owner.player.SetPSprite(PSP_WEAPON,ResolveState("Deselect"));
// check if we're waving at a dying enemy
if ( (psp.frame >= 3) && (psp.frame <= 12) && (psp.sprite == GetSpriteIndex('XZW1')) )
CheckWave();
}
private void CheckWave()
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( !hnd ) return;
for ( int i=0; i<hnd.suckableactors.Size(); i++ )
{
let a = hnd.suckableactors[i];
if ( !a || (a.Health > 0) || (a.tics == -1) || !(a.bISMONSTER || a.player) || !a.IsHostile(Owner) ) continue;
// check if we can see it
if ( !SWWMUtility.InPlayerFOV(Owner.player,a) ) continue;
// someone's dying
SWWMUtility.MarkAchievement('swwm_achievement_wave',Owner.player);
break;
}
}
static SWWMGesture SetGesture( PlayerPawn mo, int which )
@ -232,6 +251,7 @@ Class SWWMGesture : SWWMWeapon
{
let s = Demolitionist(self).mystats;
if ( s ) s.befriend++;
SWWMUtility.AchievementProgressInc('swwm_progress_friend',1,player);
}
t.bFRIENDLY = true;
if ( deathmatch )

View file

@ -462,6 +462,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);
return true;
}
return false;

View file

@ -110,9 +110,10 @@ Class SWWMHandler : EventHandler
if ( !(e.ActivationType&SPAC_Use) ) return;
if ( !e.Thing || !e.Thing.player ) return;
let w = SWWMWeapon(e.Thing.player.ReadyWeapon);
if ( !w || !w.wallponch ) return;
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);
}
// stuff for hud

View file

@ -5,6 +5,7 @@ Class Demolitionist : PlayerPawn
Vector3 dashdir;
double dashfuel, dashboost;
int dashcooldown, boostcooldown, fuelcooldown;
bool fullfuel;
bool sendtoground;
bool key_reentrant;
bool bInDefaultInventory;
@ -55,6 +56,7 @@ Class Demolitionist : PlayerPawn
Actor selflight;
Actor oldencroached;
Vector3 oldencroachedpos;
int encroachtics;
Vector3 pretelepos;
@ -63,6 +65,7 @@ Class Demolitionist : PlayerPawn
int healcooldown, healtimer, oldhealth;
bool scriptedinvul;
bool hitactivate;
transient int lastuse, failcounter, failcooldown;
@ -445,24 +448,28 @@ Class Demolitionist : PlayerPawn
}
void A_Dash()
{
vel += dashdir*dashboost;
vel += dashdir*dashboost*clamp(dashfuel/20.,0.,1.);
player.vel *= 0.;
if ( dashboost < .2 ) dashboost = 0.;
else
{
if ( swwm_extraalert ) A_AlertMonsters(swwm_uncapalert?0:800);
dashboost *= (player.cmd.buttons&BT_USER2)?.9:.1;
if ( !(player.cmd.buttons&BT_USER2) ) dashboost *= .1;
}
mystats.fuelusage += dashfuel-max(0.,dashfuel-dashboost);
double fueluse = (dashfuel-max(0.,dashfuel-dashboost))/60.;
SWWMUtility.AchievementProgressIncDouble('swwm_progress_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);
if ( (dashfuel <= 0.) || (dashboost <= 0.) )
SetStateLabel("DashEnd");
}
void A_BoostUp( bool initial = false )
{
vel += (0,0,1)*dashboost;
vel += (0,0,1)*dashboost*clamp(dashfuel/10.,0,1.);
player.vel *= 0.;
if ( dashboost < .2 ) dashboost = 0.;
else
@ -471,7 +478,9 @@ Class Demolitionist : PlayerPawn
dashboost *= (player.cmd.buttons&BT_JUMP)?.95:.4;
last_boost = level.maptime+1;
}
mystats.fuelusage += dashfuel-max(0.,dashfuel-dashboost);
double fueluse = (dashfuel-max(0.,dashfuel-dashboost))/60.;
SWWMUtility.AchievementProgressIncDouble('swwm_progress_fuel',fueluse,player);
mystats.fuelusage += fueluse;
if ( !swwm_superfuel ) dashfuel = max(0.,dashfuel-dashboost);
if ( ((dashfuel <= 0.) || (dashboost <= 0.)) )
{
@ -863,6 +872,8 @@ Class Demolitionist : PlayerPawn
CheckUnderwaterAmb();
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);
if ( !myvoice ) myvoice = CVar.GetCVar('swwm_voicetype',player);
if ( player.onground && !bNoGravity && !lastground && (waterlevel < 2) )
{
@ -942,7 +953,11 @@ Class Demolitionist : PlayerPawn
SetOrigin(newp,true);
if ( !TestMobjLocation() ) SetOrigin(oldp,true);
}
encroachtics++;
if ( !(encroachtics%GameTicRate) )
SWWMUtility.AchievementProgress('swwm_progress_step',encroachtics/GameTicRate,player);
}
else encroachtics = 0;
oldencroached = encroached;
oldencroachedpos = encroached.pos;
}
@ -952,6 +967,7 @@ Class Demolitionist : PlayerPawn
// make sure we're not getting launched because an enemy just died under our feet, because that can cause some issues
if ( oldencroached && (dashboost <= 0.) && (lastvelz >= -25) && (!oldencroached.bISMONSTER || (oldencroached.Health > 0)) ) vel += oldencroached.vel+level.Vec3Diff(oldencroachedpos,oldencroached.pos);
oldencroached = null;
encroachtics = 0;
}
if ( encroached && encroached.bSHOOTABLE && !encroached.bNODAMAGE && (lastvelz <= 0) && !(encroached is 'Demolitionist') )
{
@ -965,7 +981,7 @@ Class Demolitionist : PlayerPawn
ps.target = self;
ps.special1 = realdmg;
}
if ( !encroached.bNOBLOOD && !encroached.bINVULNERABLE )
if ( encroached && !encroached.bNOBLOOD && !encroached.bINVULNERABLE )
{
encroached.TraceBleed(realdmg,self);
encroached.SpawnBlood(pos,angle,realdmg);
@ -1046,6 +1062,7 @@ Class Demolitionist : PlayerPawn
else if ( diff.y < -(a.Radius+Radius) ) bnorm = (0,1,0);
if ( dir dot bnorm > -.6 ) continue;
}
if ( !CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) ) continue;
// large monsters will stop the player (unless hit from above if we're going at ground pound speed)
A_QuakeEx(4,4,4,10,0,128,"",QF_RELATIVE|QF_SCALEDOWN);
A_AlertMonsters(swwm_uncapalert?0:800);
@ -1057,6 +1074,7 @@ Class Demolitionist : PlayerPawn
{
if ( bumped ) continue;
bumped = true;
SWWMUtility.AchievementProgressInc('swwm_progress_bonk',1,player);
A_QuakeEx(8,8,8,16,0,128,"",QF_RELATIVE|QF_SCALEDOWN);
vel *= .2;
vel -= dir*(10+(spd*30/mass));
@ -1166,6 +1184,7 @@ Class Demolitionist : PlayerPawn
{
// headbump
bumped = true;
SWWMUtility.AchievementProgressInc('swwm_progress_bonk',1,player);
A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP);
bumptic = gametic+int(20+spd/4.);
lastbump *= .8;
@ -1260,6 +1279,7 @@ Class Demolitionist : PlayerPawn
}
// wallbump
bumped = true;
SWWMUtility.AchievementProgressInc('swwm_progress_bonk',1,player);
A_StartSound("demolitionist/bump",CHAN_DAMAGE,CHANF_OVERLAP);
bumptic = gametic+int(25+spd/4.);
lastbump *= .8;
@ -1281,7 +1301,11 @@ Class Demolitionist : PlayerPawn
// activate it
int locknum = SWWMUtility.GetLineLock(BlockingLine);
if ( !locknum || CheckKeys(locknum,false,true) )
{
hitactivate = true;
BlockingLine.Activate(self,lside,SPAC_Use);
hitactivate = false;
}
BlockingLine.Activate(self,lside,SPAC_Impact);
break;
}
@ -1391,6 +1415,8 @@ Class Demolitionist : PlayerPawn
A_DemoPain();
}
PainChance = oldpchance;
if ( (Health <= 0) && (source == self) && (flags&DMG_EXPLOSION) )
SWWMUtility.MarkAchievement('swwm_achievement_dime',player);
return realdmg;
}
override void CalcHeight()
@ -1621,6 +1647,7 @@ Class Demolitionist : PlayerPawn
}
if ( (dodge.length() > 0) && (dashcooldown <= 0) && (dashfuel > 20.) && player.cmd.buttons&BT_USER2 && (player.onground || level.IsJumpingAllowed() || (player.cmd.buttons&BT_CROUCH)) && (gamestate == GS_LEVEL) )
{
fullfuel = (dashfuel >= default.dashfuel);
dashdir = dodge.unit();
dashcooldown = 10;
dashboost = 20.;
@ -1759,6 +1786,7 @@ Class Demolitionist : PlayerPawn
{
A_StartSound("demolitionist/kick",CHAN_FOOTSTEP,CHANF_OVERLAP);
last_kick = level.maptime+1;
SWWMUtility.AchievementProgressInc('swwm_progress_jump',1,player);
}
}
bOnMobj = false;
@ -1789,6 +1817,7 @@ Class Demolitionist : PlayerPawn
// bunnyhop time
if ( (player.cmd.buttons&BT_RUN) && (level.maptime < (lastairtic+10)) && !walljump && !wallclimb )
{
SWWMUtility.AchievementProgressInc('swwm_progress_bune',1,player);
// bhop, z vel relative to vel size
if ( vel.z < 25. ) // don't ramp up too hard
vel.z += jumpvelz*(1.2+vel.length()*.01);
@ -1863,6 +1892,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);
hasrevived = true;
player.Resurrect();
player.damagecount = 0;
@ -2265,6 +2295,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);
}
else Console.Printf(StringTable.Localize("$SWWM_FINDSECRET"),player.GetUserName(),score);
if ( CheckLocalView() ) SWWMHandler.AddOneliner("findsecret",2,40);

View file

@ -51,6 +51,13 @@ Class SWWMStaticHandler : StaticEventHandler
Demolitionist(players[i].mo).CheckUnderwaterAmb(true);
}
}
if ( players[consoleplayer].mo )
{
// recheck progress on collectibles
int nc = 0;
for ( Inventory i=players[consoleplayer].mo.inv; i; i=i.inv ) if ( i is 'SWWMCollectible' ) nc++;
if ( !swwm_achievement_allcoll ) CVar.FindCVar('swwm_progress_allcoll').SetInt(nc);
}
SWWMHandler.ClearAllShaders(players[consoleplayer]);
// force a reset of the minimap zoom in case it's set beyond safe levels
double mmz = swwm_mm_zoom;
@ -93,6 +100,13 @@ Class SWWMStaticHandler : StaticEventHandler
Font.GetFont('TewiShaded');
Font.GetFont('TewiShadedInverse');
Font.GetFont('SWWMBigFont');
// iwad progress
if ( gameinfo.gametype&GAME_Doom )
SWWMUtility.AchievementProgressOr('swwm_progress_iwad',1,players[consoleplayer]);
else if ( gameinfo.gametype&GAME_Heretic )
SWWMUtility.AchievementProgressOr('swwm_progress_iwad',2,players[consoleplayer]);
else if ( gameinfo.gametype&GAME_Hexen )
SWWMUtility.AchievementProgressOr('swwm_progress_iwad',4,players[consoleplayer]);
}
override void ConsoleProcess( ConsoleEvent e )
@ -118,6 +132,34 @@ Class SWWMStaticHandler : StaticEventHandler
for ( int i=0; i<mmvars.Size(); i++ )
CVar.FindCVar(mmvars[i]).ResetToDefault();
}
else if ( e.Name ~== "swwmgetplaytime" )
{
int val = swwm_playtime;
int sec = (val%60);
int min = ((val/60)%60);
int hour = ((val/3600)%24);
int day = val/86400;
String str = "";
if ( day ) str.AppendFormat("%d days",day);
if ( hour )
{
if ( str != "" ) str = str..", ";
str.AppendFormat("%d hours",hour);
}
if ( min )
{
if ( str != "" ) str = str..", ";
str.AppendFormat("%d minutes",min);
}
if ( sec )
{
if ( str != "" ) str = str..", ";
str.AppendFormat("%d seconds",sec);
}
if ( str == "" ) Console.Printf("No Data");
else Console.Printf(str);
return;
}
}
override void NetworkProcess( ConsoleEvent e )
@ -161,6 +203,12 @@ Class SWWMStaticHandler : StaticEventHandler
override void PostUiTick()
{
if ( (gametic > 0) && !(gametic%GameTicRate) )
{
let pt = CVar.FindCVar('swwm_playtime');
int ct = pt.GetInt();
pt.SetInt(ct+1);
}
if ( gamestate != GS_LEVEL ) return;
CheckAllAchievements();
if ( !mpsent )

View file

@ -81,7 +81,7 @@ Class SWWMDamageAccumulator : Thinker
{
Super.Tick();
// so many damn safeguards in this
if ( !victim )
if ( !victim || (victim.Health <= 0) )
{
Destroy();
return;
@ -396,3 +396,42 @@ Class SWWMCorpseCleaner : Thinker
}
}
}
Class SWWMFlyTracker : Thinker
{
Actor tracked, instigator;
Vector3 startpos;
int gracepd;
static void Track( Actor b, Actor whomst )
{
if ( !b || !whomst ) return;
let ti = ThinkerIterator.Create("SWWMFlyTracker",STAT_USER);
SWWMFlyTracker ffd;
while ( ffd = SWWMFlyTracker(ti.Next()) )
{
if ( ffd.tracked != b ) continue;
ffd.instigator = whomst;
return;
}
ffd = new("SWWMFlyTracker");
ffd.ChangeStatNum(STAT_USER);
ffd.tracked = b;
ffd.instigator = whomst;
ffd.startpos = b.pos;
}
override void Tick()
{
if ( !tracked || tracked.bFLOAT || tracked.bNOGRAVITY || (tracked.waterlevel > 1) || (tracked.pos.z <= tracked.floorz) || !tracked.TestMobjZ(false) )
{
gracepd++;
if ( gracepd < 10 ) return;
if ( instigator ) SWWMUtility.AchievementProgress('swwm_progress_flight',int(level.Vec3Diff(startpos,tracked.pos).length()),instigator.player);
Destroy();
return;
}
gracepd = 0;
}
}

View file

@ -43,6 +43,7 @@ Class SWWMStats : Thinker
Array<bool> secretdone;
// hackaround for stuff getting lost
Array<Class<SWWMCollectible> > ownedcollectibles;
int plushuses;
// for pistol start info (to avoid it within hubs)
int lastcluster;
@ -61,7 +62,7 @@ Class SWWMStats : Thinker
Class<Weapon> which = myplayer.ReadyWeapon?myplayer.ReadyWeapon.GetClass():null;
if ( inflictor is 'Weapon' ) which = Weapon(inflictor).GetClass();
if ( which is 'DualExplodiumGun' ) which = 'ExplodiumGun'; // don't credit sister weapon
if ( inflictor.FindInventory("ParriedBuff") ) which = 'DoomWeapon'; // gross hack
if ( inflictor && inflictor.FindInventory("ParriedBuff") ) which = 'DoomWeapon'; // gross hack
// properly credit some projectiles to their respective gun
else if ( inflictor is 'AirBullet' ) which = 'DeepImpact';
else if ( inflictor is 'PusherProjectile' ) which = 'PusherWeapon';
@ -200,6 +201,14 @@ Class SWWMCredits : Thinker
{
PlayerInfo myplayer;
int credits, hcredits;
bool cheated;
static void HasCheated( PlayerInfo p )
{
let c = Find(p);
if ( !c ) return;
c.cheated = true;
}
static void Give( PlayerInfo p, int amount, int hamount = 0 )
{
@ -220,6 +229,9 @@ Class SWWMCredits : Thinker
s.hiscore = c.credits;
s.hhiscore = c.hcredits;
}
if ( c.cheated ) return;
if ( c.hcredits > 0 ) SWWMUtility.AchievementProgress('swwm_progress_dosh',1000000000,p);
else SWWMUtility.AchievementProgress('swwm_progress_dosh',c.credits,p);
}
static clearscope bool CanTake( PlayerInfo p, int amount, int hamount = 0 )

View file

@ -9,6 +9,8 @@ enum EDoExplosionFlags
DE_NOTMISSILE = 16, // instigator is the source itself (normally it'd be its target pointer)
DE_EXTRAZTHRUST = 32, // applies a higher Z thrust to enemies on ground
DE_HOWL = 64, // 25% chance for hit enemies to howl
DE_COUNTENEMIES = 128, // only count hits for hostiles
DE_COUNTSTEALTH = 256, // only count hits for inactive monsters
};
Class SWWMUtility
@ -899,13 +901,15 @@ Class SWWMUtility
if ( (flags&DE_BLAST) && a.bCANBLAST && !a.bDONTBLAST ) a.bBLASTED = true;
}
// hit it
nhit++;
bool inactive = (!a.player&&!a.target);
bool hostile = (Instigator&&a.IsHostile(Instigator)&&(a.bISMONSTER||a.player));
if ( (!(flags&DE_COUNTENEMIES) || hostile) && (!(flags&DE_COUNTSTEALTH) || inactive) ) nhit++;
int dmg = int(Damage*damagescale);
if ( dmg <= 0 ) continue; // no harm
int ndmg = a.DamageMobj(Source,Instigator,dmg,(DamageType=='')?Source.DamageType:DamageType,DMG_EXPLOSION,atan2(-dir.y,-dir.x));
if ( a && !(flags&DE_NOBLEED) ) a.TraceBleed((ndmg>0)?ndmg:dmg,Source);
if ( (flags&DE_HOWL) && a && a.bISMONSTER && !Random[DoBlast](0,3) ) a.Howl();
if ( !a || (a.Health <= 0) ) nkill++;
if ( (flags&DE_HOWL) && a && (a.Health > 0) && a.bISMONSTER && !Random[DoBlast](0,3) ) a.Howl();
if ( (!a || (a.Health <= 0)) && (!(flags&DE_COUNTENEMIES) || hostile) && (!(flags&DE_COUNTSTEALTH) || inactive) ) nkill++;
}
return nhit, nkill;
}
@ -1625,6 +1629,47 @@ Class SWWMUtility
return false, checkme;
}
// achievement helpers
static clearscope void MarkAchievement( Name mvar, PlayerInfo p = null )
{
if ( !p || (p != players[consoleplayer]) ) return;
let cv = CVar.FindCVar(mvar);
if ( !cv ) return;
if ( cv.GetInt() < 1 ) cv.SetInt(1);
}
static clearscope void AchievementProgress( Name pvar, int val, PlayerInfo p = null )
{
if ( !p || (p != players[consoleplayer]) ) return;
let cv = CVar.FindCVar(pvar);
if ( !cv ) return;
int cval = cv.GetInt();
cv.SetInt(max(cval,val));
}
static clearscope void AchievementProgressInc( Name pvar, int inc, PlayerInfo p = null )
{
if ( !p || (p != players[consoleplayer]) ) return;
let cv = CVar.FindCVar(pvar);
if ( !cv ) return;
int cval = cv.GetInt();
cv.SetInt(cval+inc);
}
static clearscope void AchievementProgressIncDouble( Name pvar, double inc, PlayerInfo p = null )
{
if ( !p || (p != players[consoleplayer]) ) return;
let cv = CVar.FindCVar(pvar);
if ( !cv ) return;
double cval = cv.GetFloat();
cv.SetFloat(cval+inc);
}
static clearscope void AchievementProgressOr( Name pvar, int val, PlayerInfo p = null )
{
if ( !p || (p != players[consoleplayer]) ) return;
let cv = CVar.FindCVar(pvar);
if ( !cv ) return;
int cval = cv.GetInt();
cv.SetInt(cval|val);
}
// full reset of inventory (excluding collectibles, and optionally resetting the score)
static play void WipeInventory( Actor mo, bool resetscore = false, bool allplayers = false )
{

View file

@ -199,6 +199,7 @@ Class ParryField : Actor
critsnd = true;
}
if ( s ) s.parries++;
SWWMUtility.AchievementProgressInc('swwm_progress_parry',1,master.player);
}
if ( --special1 <= 0 ) Destroy();
}
@ -390,7 +391,10 @@ extend Class SWWMWeapon
{
int locknum = SWWMUtility.GetLineLock(ut.uses[i].hitline);
if ( !locknum || CheckKeys(locknum,false,true) )
{
SWWMUtility.AchievementProgressInc('swwm_progress_slemg',1,player);
ut.uses[i].hitline.RemoteActivate(self,ut.uses[i].hitside,SPAC_Use,ut.uses[i].pos);
}
if ( !(ut.uses[i].hitline.activation&SPAC_UseThrough) ) break;
}
}

View file

@ -546,14 +546,18 @@ Class HellblazerRavager : HellblazerMissile
Class HellblazerWarhead : HellblazerMissile
{
int nkill;
void A_BlazerWarheadExplode()
{
nkill = 0;
bForceXYBillboard = true;
bRollSprite = false;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("WumboRocketBlast",150);
A_SetScale(7.);
SWWMUtility.DoExplosion(self,1500,600000,400,200);
int nhit;
[nhit, nkill] = SWWMUtility.DoExplosion(self,1500,600000,400,200,DE_COUNTENEMIES);
A_NoGravity();
A_QuakeEx(9,9,9,150,0,12000,"",QF_RELATIVE|QF_SCALEDOWN,falloff:4000,rollIntensity:2.);
A_StopSound(CHAN_BODY);
@ -594,7 +598,11 @@ Class HellblazerWarhead : HellblazerMissile
void A_WarheadSub()
{
if ( special1 < 40 )
SWWMUtility.DoExplosion(self,320-special1*8,600000-special1*12000,200+special1*30);
{
int nhit, nkil;
[nhit, nkil] = SWWMUtility.DoExplosion(self,320-special1*8,600000-special1*12000,200+special1*30,flags:DE_COUNTENEMIES);
nkill += nkil;
}
special1++;
if ( (special1 <= 30) && !(special1%2) )
{
@ -643,6 +651,7 @@ Class HellblazerWarhead : HellblazerMissile
c.angle = ang;
c.pitch = pt;
c.target = target;
c.master = self;
}
}
}
@ -658,9 +667,13 @@ Class HellblazerWarhead : HellblazerMissile
TNT1 A 1
{
A_WarheadSub();
A_FadeOut(.05);
if ( special1 >= 40 )
{
if ( target ) SWWMUtility.AchievementProgress('swwm_progress_slayer',invoker.nkill,target.player);
Destroy();
}
}
Stop;
Wait;
}
}
@ -1221,7 +1234,9 @@ Class HellblazerWarheadArm : Actor
TNT1 A 1
{
Spawn("HellblazerWarheadTrail",pos);
SWWMUtility.DoExplosion(self,20+reactiontime*4,3000+500*reactiontime,120+4*reactiontime);
int nhit, nkill;
[nhit, nkill] = SWWMUtility.DoExplosion(self,20+reactiontime*4,3000+500*reactiontime,120+4*reactiontime,flags:DE_COUNTENEMIES);
if ( HellblazerWarhead(master) ) HellblazerWarhead(master).nkill += nkill;
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,5);
let s = Spawn("SWWMHalfSmoke",pos);
s.vel = pvel+vel*.2;

View file

@ -421,6 +421,7 @@ Class Wallbuster : SWWMWeapon
[x2, y2, z2] = swwm_CoordUtil.GetAxes(BulletSlope(),angle,roll);
int alertness = 0;
// second pass, play the fire effects
int salts = 0;
for ( int i=0; i<num; i++ )
{
// get physical index
@ -446,12 +447,17 @@ Class Wallbuster : SWWMWeapon
A_StartSound(sounds[which],CHAN_WEAPON,CHANF_OVERLAP,1./(howmany**rfact),.6-howmany*.004,1.-howmany*.015);
if ( which == 0 ) redflashstr = max(120,redflashstr+10);
else if ( which == 1 ) redflashstr = max(90,redflashstr+8);
else if ( which == 2 ) blueflashstr = max(160,blueflashstr+10);
else if ( which == 2 )
{
blueflashstr = max(160,blueflashstr+10);
salts++;
}
else if ( which == 3 ) redflashstr = max(60,redflashstr+6);
A_CBTFlash(flashes[which],i);
if ( alertness > louds[which] ) alertness += louds[which]/4;
else alertness += louds[which];
}
if ( salts >= 25 ) SWWMUtility.MarkAchievement('swwm_achievement_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

@ -343,6 +343,7 @@ Class BusterWall : Thinker
{
let s = SWWMStats.Find(Instigator.player);
if ( s ) s.busts++;
SWWMUtility.AchievementProgressInc('swwm_progress_bustin',1,Instigator.player);
}
bust.busted = true;
bust.busttics = 0;

View file

@ -445,6 +445,7 @@ Class EvisceratorProjLight : PaletteLight
Class EvisceratorProj : Actor
{
double heat;
Vector3 startpos;
Default
{
Obituary "$O_EVISCERATOR";
@ -463,11 +464,17 @@ Class EvisceratorProj : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
startpos = pos;
if ( waterlevel <= 0 ) vel.z += 3;
heat = 1.5;
}
action void A_EvisExplode()
{
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);
}
bForceXYBillboard = true;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("BigRocketBlast",50);

View file

@ -419,10 +419,20 @@ Class YnykronImpact : Actor
gc.DoTheThing(true);
gc.Amount--;
}
else if ( !tracer.FindInventory("GrilledCheeseSafeguard") ) tracer.DamageMobj(self,target,int.max,'Ynykron',DMG_FORCED|DMG_THRUSTLESS);
else if ( !tracer.FindInventory("GrilledCheeseSafeguard") )
{
tracer.DamageMobj(self,target,int.max,'Ynykron',DMG_FORCED|DMG_THRUSTLESS);
if ( target && tracer && (tracer.Health > 0) )
SWWMUtility.MarkAchievement('swwm_achievement_god',target.player);
}
if ( tracer && (tracer.Health <= 0) )
{
if ( tracer.player ) PlayerGone.FeckOff(tracer);
if ( tracer.player )
{
if ( tracer == target )
SWWMUtility.MarkAchievement('swwm_achievement_oopsie',tracer.player);
PlayerGone.FeckOff(tracer);
}
if ( tracer.FindState("YnykronDeath",true) )
tracer.SetStateLabel("YnykronDeath"); // dedicated state
else
@ -437,6 +447,10 @@ Class YnykronImpact : Actor
let r = Spawn("AshenRemains",tracer.pos);
r.scale *= tracer.radius/16.;
}
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);
}
}
if ( YnykronShot(master) )
@ -499,7 +513,10 @@ Class YnykronImpact : Actor
dirto /= dist;
int trad = int(max(t.radius,t.height));
if ( t && YnykronShot(master) )
{
YnykronShot(master).hitlist.Push(t);
if ( t.bBOSS ) YnykronShot(master).hitboss = true;
}
// spawn blast that will propagate
let b = Spawn("YnykronDelayedImpact",t.pos);
Vector3 ofs = level.Vec3Diff(t.pos,level.Vec3Offset(pos,dirto*min(rad,dist)));
@ -666,7 +683,10 @@ Class YnykronBeam : Actor
continue;
int trad = int(max(t.hitlist[i].hitactor.radius,t.hitlist[i].hitactor.height));
if ( t.hitlist[i].hitactor && YnykronShot(master) )
{
YnykronShot(master).hitlist.Push(t.hitlist[i].hitactor);
if ( t.hitlist[i].hitactor.bBOSS ) YnykronShot(master).hitboss = true;
}
// spawn blast that will propagate
let b = Spawn("YnykronImpact",t.hitlist[i].hitlocation);
b.tracer = t.HitList[i].hitactor;
@ -763,7 +783,10 @@ Class YnykronBeam : Actor
continue;
int trad = int(max(it.hitlist[i].hitactor.radius,it.hitlist[i].hitactor.height));
if ( it.hitlist[i].hitactor && YnykronShot(master) )
{
YnykronShot(master).hitlist.Push(it.hitlist[i].hitactor);
if ( it.hitlist[i].hitactor.bBOSS ) YnykronShot(master).hitboss = true;
}
// spawn blast that will propagate
let b = Spawn("YnykronImpact",it.hitlist[i].hitlocation);
b.tracer = it.hitlist[i].hitactor;
@ -1040,6 +1063,8 @@ Class YnykronImpactRing : Actor
Class YnykronShot : Actor
{
Array<Actor> hitlist;
bool hitboss;
int enemykills;
int beamcount;
int blastcount;
int lastimpact;
@ -1115,13 +1140,19 @@ Class YnykronShot : Actor
}
}
// wait until we're no longer needed and all effects are over
if ( IsActorPlayingSound(CHAN_VOICE) || (beamcount > 0) || (blastcount > 0) )
{
special1 = min(special1,50);
if ( (beamcount > 0) || (blastcount > 0) )
return;
if ( target && enemykills )
{
if ( (enemykills == 1) && !hitboss )
SWWMUtility.MarkAchievement('swwm_achievement_oneguy',target.player);
SWWMUtility.AchievementProgress('swwm_progress_ezkill',enemykills,target.player);
enemykills = 0;
}
// we're done here, but wait for a while just in case
if ( special1 > 350 ) Destroy();
if ( IsActorPlayingSound(CHAN_VOICE) )
return;
// we're done here
Destroy();
}
}
@ -2395,10 +2426,20 @@ Class YnykronSingularity : Actor
gc.DoTheThing(true);
gc.Amount--;
}
else if ( !a.FindInventory("GrilledCheeseSafeguard") ) a.DamageMobj(self,target,int.max,'Ynykron',DMG_FORCED|DMG_THRUSTLESS);
else if ( !a.FindInventory("GrilledCheeseSafeguard") )
{
a.DamageMobj(self,target,int.max,'Ynykron',DMG_FORCED|DMG_THRUSTLESS);
if ( target && a && (a.Health > 0) )
SWWMUtility.MarkAchievement('swwm_achievement_god',target.player);
}
if ( a && (a.Health <= 0) )
{
if ( a.player ) PlayerGone.FeckOff(a);
if ( a.player )
{
if ( a == target )
SWWMUtility.MarkAchievement('swwm_achievement_oopsie',a.player);
PlayerGone.FeckOff(a);
}
if ( a.FindState("YnykronAltDeath",true) )
a.SetStateLabel("YnykronAltDeath"); // dedicated state
else
@ -2408,6 +2449,8 @@ Class YnykronSingularity : Actor
a.A_ChangeLinkFlags(false); // remove from blockmap, should guarantee archviles not raising this
IDontFeelSoGood.DeletThis(a,true); // ensures corpse is deleted too
}
if ( target && a.FindInventory("EndgameBossMarker") )
SWWMUtility.MarkAchievement('swwm_achievement_ligma',target.player);
}
if ( !a || (a.Health <= 0) )
specialf2 += min(100.,capmass*.6); // partial absorption

View file

@ -211,6 +211,7 @@ Class DeepImpact : SWWMWeapon
}
let ti = ThinkerIterator.Create("Actor");
Actor m;
let s = Demolitionist(self).mystats;
while ( m = Actor(ti.Next()) )
{
if ( !(SWWMUtility.ValidProjectile(m) && (m.target != self)) ) continue;
@ -231,6 +232,8 @@ Class DeepImpact : SWWMWeapon
let pb = Inventory(Spawn("ParriedBuff"));
pb.AttachToOwner(m);
}
if ( s ) s.parries++;
SWWMUtility.AchievementProgressInc('swwm_progress_parry',1,player);
}
int numpt = Random[Impact](7,12);
for ( int i=0; i<numpt; i++ )

View file

@ -618,6 +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);
break;
default:
st = new("SpreadgunTracer");

View file

@ -780,6 +780,7 @@ Class CorrodeDebuff : Inventory
// forcibly update
wasalive = true;
cnt = -1;
if ( instigator ) SWWMUtility.AchievementProgressInc('swwm_progress_acid',1,instigator.player);
}
override void DoEffect()
{
@ -1186,6 +1187,7 @@ Class TheBall : Actor
s.vel = pvel;
}
crit = true;
if ( target ) SWWMUtility.AchievementProgressInc('swwm_progress_balls',1,target.player);
}
SWWMUtility.DoKnockback(victim,vel.unit(),slamforce);
bool bleeds = (victim && !victim.bINVULNERABLE && !victim.bNOBLOOD && !victim.bDORMANT && is_schutt);
@ -1215,6 +1217,8 @@ 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);
// only rip shootables
if ( (slamforce > girth) && is_schutt )
{

View file

@ -1127,6 +1127,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);
}
else
{

View file

@ -9,6 +9,8 @@ Class ExplodiumGun : SWWMWeapon
double casex, casey;
transient ui TextureID WeaponBox;
transient ui Font TewiFont;
transient Actor deadeye_tgt;
transient int deadeye_cnt;
Property ClipCount : ClipCount;
@ -110,6 +112,17 @@ Class ExplodiumGun : SWWMWeapon
SWWMBulletTrail.DoTrail(self,origin,dir,10000,2);
if ( d.HitType == TRACE_HitActor )
{
if ( invoker.deadeye_tgt && (d.HitActor != invoker.deadeye_tgt) )
{
invoker.deadeye_tgt = null;
invoker.deadeye_cnt = 0;
}
else
{
invoker.deadeye_tgt = d.HitActor;
invoker.deadeye_cnt++;
SWWMUtility.AchievementProgress('swwm_progress_explogun',invoker.deadeye_cnt,player);
}
int dmg = 15;
// might as well apply explosion on top
if ( dmg >= d.HitActor.Health ) dmg += 20;
@ -131,33 +144,38 @@ Class ExplodiumGun : SWWMWeapon
b.pitch = asin(d.HitDir.z);
b.target = self;
}
else if ( d.HitType != TRACE_HitNone )
else
{
Vector3 hitnormal = -d.HitDir;
if ( d.HitType == TRACE_HitFloor )
invoker.deadeye_tgt = null;
invoker.deadeye_cnt = 0;
if ( d.HitType != TRACE_HitNone )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
else hitnormal = d.HitSector.floorplane.Normal;
Vector3 hitnormal = -d.HitDir;
if ( d.HitType == TRACE_HitFloor )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
else hitnormal = d.HitSector.floorplane.Normal;
}
else if ( d.HitType == TRACE_HitCeiling )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
else hitnormal = d.HitSector.ceilingplane.Normal;
}
else if ( d.HitType == TRACE_HitWall )
{
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
if ( !d.LineSide ) hitnormal *= -1;
}
let p = Spawn("SWWMBulletImpact",d.HitLocation+hitnormal*0.01);
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
let b = Spawn("ExplodiumBulletImpact",d.HitLocation+hitnormal*4.);
b.angle = atan2(hitnormal.y,hitnormal.x);
b.pitch = asin(-hitnormal.z);
b.target = self;
if ( swwm_omnibust ) BusterWall.BustLinetrace(d,50,self,d.HitDir,d.HitLocation.z);
}
else if ( d.HitType == TRACE_HitCeiling )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
else hitnormal = d.HitSector.ceilingplane.Normal;
}
else if ( d.HitType == TRACE_HitWall )
{
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
if ( !d.LineSide ) hitnormal *= -1;
}
let p = Spawn("SWWMBulletImpact",d.HitLocation+hitnormal*0.01);
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
let b = Spawn("ExplodiumBulletImpact",d.HitLocation+hitnormal*4.);
b.angle = atan2(hitnormal.y,hitnormal.x);
b.pitch = asin(-hitnormal.z);
b.target = self;
if ( swwm_omnibust ) BusterWall.BustLinetrace(d,50,self,d.HitDir,d.HitLocation.z);
}
for ( int i=0; i<6; i++ )
{
@ -283,7 +301,12 @@ Class ExplodiumGun : SWWMWeapon
XZW1 A -1;
Stop;
Select:
XZW2 B 2 A_FullRaise();
XZW2 B 2
{
invoker.deadeye_tgt = null;
invoker.deadeye_cnt = 0;
A_FullRaise();
}
XZW2 CDEFGH 2;
Goto Ready;
Ready:
@ -348,6 +371,8 @@ Class ExplodiumGun : SWWMWeapon
Reload:
XZW2 A 1
{
invoker.deadeye_tgt = null;
invoker.deadeye_cnt = 0;
if ( invoker.clipcount >= invoker.default.clipcount ) return ResolveState("CheckBullet");
A_PlayerReload();
if ( invoker.clipcount <= 0 ) return ResolveState("ReloadEmpty");
@ -455,6 +480,8 @@ Class DualExplodiumGun : SWWMWeapon
double casex, casey, lcasex, lcasey;
transient ui TextureID WeaponBox;
transient ui Font TewiFont;
transient Actor deadeye_tgt;
transient int deadeye_cnt;
Property ClipCount : ClipCount;
@ -552,6 +579,17 @@ Class DualExplodiumGun : SWWMWeapon
SWWMBulletTrail.DoTrail(self,origin,dir,10000,2);
if ( d.HitType == TRACE_HitActor )
{
if ( invoker.deadeye_tgt && (d.HitActor != invoker.deadeye_tgt) )
{
invoker.deadeye_tgt = null;
invoker.deadeye_cnt = 0;
}
else
{
invoker.deadeye_tgt = d.HitActor;
invoker.deadeye_cnt++;
SWWMUtility.AchievementProgress('swwm_progress_explogun',invoker.deadeye_cnt,player);
}
int dmg = 15;
// might as well apply explosion on top
if ( dmg >= d.HitActor.Health ) dmg += 20;
@ -573,33 +611,38 @@ Class DualExplodiumGun : SWWMWeapon
b.pitch = asin(d.HitDir.z);
b.target = self;
}
else if ( d.HitType != TRACE_HitNone )
else
{
Vector3 hitnormal = -d.HitDir;
if ( d.HitType == TRACE_HitFloor )
invoker.deadeye_tgt = null;
invoker.deadeye_cnt = 0;
if ( d.HitType != TRACE_HitNone )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
else hitnormal = d.HitSector.floorplane.Normal;
Vector3 hitnormal = -d.HitDir;
if ( d.HitType == TRACE_HitFloor )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.top.Normal;
else hitnormal = d.HitSector.floorplane.Normal;
}
else if ( d.HitType == TRACE_HitCeiling )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
else hitnormal = d.HitSector.ceilingplane.Normal;
}
else if ( d.HitType == TRACE_HitWall )
{
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
if ( !d.LineSide ) hitnormal *= -1;
}
let p = Spawn("SWWMBulletImpact",d.HitLocation+hitnormal*0.01);
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
let b = Spawn("ExplodiumBulletImpact",d.HitLocation+hitnormal*4.);
b.angle = atan2(hitnormal.y,hitnormal.x);
b.pitch = asin(-hitnormal.z);
b.target = self;
if ( swwm_omnibust ) BusterWall.BustLinetrace(d,50,self,d.HitDir,d.HitLocation.z);
}
else if ( d.HitType == TRACE_HitCeiling )
{
if ( d.Hit3DFloor ) hitnormal = -d.Hit3DFloor.bottom.Normal;
else hitnormal = d.HitSector.ceilingplane.Normal;
}
else if ( d.HitType == TRACE_HitWall )
{
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
if ( !d.LineSide ) hitnormal *= -1;
}
let p = Spawn("SWWMBulletImpact",d.HitLocation+hitnormal*0.01);
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
let b = Spawn("ExplodiumBulletImpact",d.HitLocation+hitnormal*4.);
b.angle = atan2(hitnormal.y,hitnormal.x);
b.pitch = asin(-hitnormal.z);
b.target = self;
if ( swwm_omnibust ) BusterWall.BustLinetrace(d,50,self,d.HitDir,d.HitLocation.z);
}
for ( int i=0; i<6; i++ )
{
@ -674,7 +717,12 @@ Class DualExplodiumGun : SWWMWeapon
States
{
Select:
XZW2 B 2 A_FullRaise();
XZW2 B 2
{
invoker.deadeye_tgt = null;
invoker.deadeye_cnt = 0;
A_FullRaise();
}
XZW2 C 2;
XZW2 D 2 { player.SetPSprite(PSP_WEAPON+1,ResolveState("LeftSelect")); }
XZW2 EFGHAA 2;
@ -789,7 +837,12 @@ Class DualExplodiumGun : SWWMWeapon
XZWB A 1;
Goto LeftReady;
Reload:
XZW2 A 9 { player.SetPSPrite(PSP_WEAPON+1,ResolveState("LeftLower")); }
XZW2 A 9
{
invoker.deadeye_tgt = null;
invoker.deadeye_cnt = 0;
player.SetPSPrite(PSP_WEAPON+1,ResolveState("LeftLower"));
}
XZW2 A 1
{
A_PlayerReload();
@ -845,7 +898,12 @@ Class DualExplodiumGun : SWWMWeapon
XZW2 A 0 { player.SetPSPrite(PSP_WEAPON+1,ResolveState("LeftRaise")); }
Goto Ready;
LeftReload:
XZWB A 9 { player.SetPSPrite(PSP_WEAPON,ResolveState("Lower")); }
XZWB A 9
{
invoker.deadeye_tgt = null;
invoker.deadeye_cnt = 0;
player.SetPSPrite(PSP_WEAPON,ResolveState("Lower"));
}
XZWB A 1
{
A_PlayerReload();

View file

@ -56,6 +56,7 @@ Class HitListEntry
Actor hitactor;
Vector3 hitlocation, x;
int hitdamage;
bool pastwall; // used by silver bullet
}
Class CandyBeamTracer : LineTracer
@ -536,6 +537,26 @@ Class CandyGunProj : Actor
}
void A_BlowUp()
{
bool bossbrains = false;
for ( Actor a=CurSector.thinglist; a; a=a.snext )
{
if ( a is 'BossBrain' )
{
let ti = ThinkerIterator.Create('BossEye');
if ( ti.Next() )
{
bossbrains = true;
break;
}
}
else if ( a is 'BossEye' )
{
bossbrains = true;
break;
}
}
if ( bossbrains && target )
SWWMUtility.MarkAchievement('swwm_achievement_yeet',target.player);
angle = atan2(cvel.y,cvel.x);
pitch = asin(-cvel.z);
bNOGRAVITY = true;

View file

@ -8,6 +8,7 @@ Class WallPenetrate
Line hitline;
Sector hitsector;
F3DFloor hitffloor;
bool pastwall;
}
Class AuxiliarySilverBulletTracer : LineTracer
@ -27,6 +28,7 @@ Class AuxiliarySilverBulletTracer : LineTracer
Class SilverBulletTracer : SpreadSlugTracer
{
bool pastwall;
Array<WallPenetrate> WallPenetrateList;
override ETraceStatus TraceCallback()
@ -55,6 +57,7 @@ Class SilverBulletTracer : SpreadSlugTracer
ent.hitactor = Results.HitActor;
ent.hitlocation = Results.HitPos;
ent.x = Results.HitVector;
ent.pastwall = pastwall;
if ( (Results.HitActor.Health >= int(penetration)) || Results.HitActor.bNODAMAGE )
{
ent.hitdamage = int(penetration);
@ -94,7 +97,9 @@ Class SilverBulletTracer : SpreadSlugTracer
wp.penetration = int(penetration);
wp.hitnormal = (-Results.HitLine.delta.y,Results.HitLine.delta.x,0).unit();
if ( !Results.Side ) wp.hitnormal *= -1;
wp.pastwall = pastwall;
WallPenetrateList.Push(wp);
pastwall = true;
penetration = max(0,penetration-i*4);
// trace backwards to find exit surface
let at = new("AuxiliarySilverBulletTracer");
@ -124,6 +129,7 @@ Class SilverBulletTracer : SpreadSlugTracer
wp2.hitnormal = at.Results.HitSector.ceilingplane.Normal;
else if ( at.Results.HitType == TRACE_HitFloor )
wp2.hitnormal = at.Results.HitSector.floorplane.Normal;
wp2.pastwall = pastwall;
WallPenetrateList.Push(wp2);
}
return TRACE_Skip;
@ -162,7 +168,9 @@ Class SilverBulletTracer : SpreadSlugTracer
wp.hitnormal = Results.HitSector.ceilingplane.Normal;
else if ( Results.HitType == TRACE_HitFloor )
wp.hitnormal = Results.HitSector.floorplane.Normal;
wp.pastwall = pastwall;
WallPenetrateList.Push(wp);
pastwall = true;
penetration = max(0,penetration-i*4);
// trace backwards to find exit surface
let at = new("AuxiliarySilverBulletTracer");
@ -192,6 +200,7 @@ Class SilverBulletTracer : SpreadSlugTracer
wp2.hitnormal = at.Results.HitSector.ceilingplane.Normal;
else if ( at.Results.HitType == TRACE_HitFloor )
wp2.hitnormal = at.Results.HitSector.floorplane.Normal;
wp2.pastwall = pastwall;
WallPenetrateList.Push(wp2);
}
return TRACE_Skip;
@ -249,6 +258,7 @@ Class SilverBullet : SWWMWeapon
ui int lastammo;
int clipcount;
double casex, casey;
int nkills;
transient ui TextureID WeaponBox[2], ZoomBar, BulletIcon[2], AmmoIcon[2];
transient ui Font TewiFont;
@ -433,17 +443,24 @@ Class SilverBullet : SWWMWeapon
}
for ( int i=0; i<t.HitList.Size(); i++ )
{
int realdmg = t.HitList[i].HitDamage;
SWWMDamageAccumulator.Accumulate(t.HitList[i].HitActor,realdmg,invoker,self,'shot',false,DMG_FOILINVUL);
SWWMUtility.DoKnockback(t.HitList[i].HitActor,t.HitList[i].x+(0,0,0.025),realdmg*20.*FRandom[SilverBullet](.8,1.2));
SWWMUtility.DoKnockback(t.HitList[i].HitActor,t.HitList[i].x+(0,0,0.025),t.Hitlist[i].HitDamage*20.*FRandom[SilverBullet](.8,1.2));
int dmg = t.HitList[i].HitActor.DamageMobj(invoker,self,t.Hitlist[i].HitDamage,'shot',DMG_FOILINVUL|DMG_USEANGLE|DMG_THRUSTLESS,atan2(t.Results.HitVector.y,t.Results.HitVector.x));
if ( (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);
}
if ( t.HitList[i].HitActor && !t.HitList[i].HitActor.bNOBLOOD && !t.HitList[i].HitActor.bDORMANT )
{
t.HitList[i].HitActor.TraceBleed(realdmg,self);
t.HitList[i].HitActor.SpawnBlood(t.HitList[i].HitLocation,atan2(t.HitList[i].x.y,t.HitList[i].x.x)+180,realdmg);
t.HitList[i].HitActor.TraceBleed(dmg,self);
t.HitList[i].HitActor.SpawnBlood(t.HitList[i].HitLocation,atan2(t.HitList[i].x.y,t.HitList[i].x.x)+180,dmg);
t.HitList[i].HitActor.A_StartSound("silverbullet/flesh",CHAN_DAMAGE,CHANF_OVERLAP,1.,2.);
let p = Spawn("SilverImpact",t.HitList[i].HitLocation);
p.special1 = 1;
p.target = self;
p.master = invoker;
p.bAMBUSH = t.HitList[i].pastwall;
}
else
{
@ -451,6 +468,8 @@ Class SilverBullet : SWWMWeapon
p.angle = atan2(t.HitList[i].x.y,t.HitList[i].x.x)+180;
p.pitch = asin(t.HitList[i].x.z);
p.target = self;
p.master = invoker;
p.bAMBUSH = t.HitList[i].pastwall;
}
}
LineTracer faketracer = new("LineTracer");
@ -462,6 +481,8 @@ Class SilverBullet : SWWMWeapon
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
p.target = self;
p.master = invoker;
p.bAMBUSH = t.WallPenetrateList[i].pastwall;
if ( t.WallPenetrateList[i].hittype == TRACE_HitWall )
t.WallPenetrateList[i].hitline.Activate(self,t.WallPenetrateList[i].hitside,SPAC_Impact);
if ( swwm_omnibust )
@ -497,15 +518,45 @@ Class SilverBullet : SWWMWeapon
p.angle = atan2(hitnormal.y,hitnormal.x);
p.pitch = asin(-hitnormal.z);
p.target = self;
p.master = invoker;
if ( t.WallPenetrateList.Size() > 0 ) p.bAMBUSH = true;
if ( t.Results.HitType == TRACE_HitWall ) t.Results.HitLine.RemoteActivate(self,t.Results.Side,SPAC_Impact,t.Results.HitPos);
if ( swwm_omnibust ) BusterWall.Bust(t.Results,int(t.penetration),self,t.Results.HitVector,t.Results.HitPos.z);
}
for ( int i=0; i<t.Results.Distance; i+=16 )
if ( t.WallPenetrateList.Size() > 0 )
{
Vector3 ofs = level.Vec3Offset(origin,dir*i);
if ( !level.IsPointInLevel(ofs) ) continue;
let s = Spawn("SilverAirRip",ofs);
Vector3 start = origin;
Vector3 end = t.WallPenetrateList[0].hitpos;
Vector3 dir = level.Vec3Diff(start,end);
double dist = dir.length();
dir /= dist;
for ( int i=0; i<dist; i+=16 )
{
let s = Spawn("SilverAirRip",level.Vec3Offset(start,dir*i));
s.target = self;
s.master = invoker;
}
for ( int i=1; i<t.WallPenetrateList.Size(); i+=2 )
{
start = t.WallPenetrateList[i].hitpos;
if ( i >= t.WallPenetrateList.Size()-1 ) end = t.Results.HitPos;
else end = t.WallPenetrateList[i+1].hitpos;
dir = level.Vec3Diff(start,end);
dist = dir.length();
for ( int j=0; j<dist; j+=16 )
{
let s = Spawn("SilverAirRip",level.Vec3Offset(start,dir*j));
s.target = self;
s.master = invoker;
s.bAMBUSH = true;
}
}
}
else for ( int i=0; i<t.Results.Distance; i+=16 )
{
let s = Spawn("SilverAirRip",level.Vec3Offset(origin,dir*i));
s.target = self;
s.master = invoker;
}
}
action void ProcessAltTraceHit( FatChodeTracer t, Vector3 origin, Vector3 dir )
@ -620,7 +671,9 @@ Class SilverBullet : SWWMWeapon
sst.shootthroughlist.Clear();
sst.waterhitlist.Clear();
sst.wallpenetratelist.Clear();
sst.pastwall = false;
sst.Trace(origin,level.PointInSector(origin.xy),x2,20000.,TRACE_HitSky);
invoker.nkills = 0;
ProcessTraceHit(sst,origin,x2);
}
for ( int i=0; i<16; i++ )

View file

@ -55,7 +55,14 @@ Class SilverAirRip : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
SWWMUtility.DoExplosion(self,40,2000,40,ignoreme:target);
int nhit, nkill;
[nhit, nkill] = SWWMUtility.DoExplosion(self,40,2000,40,flags:DE_COUNTENEMIES,ignoreme:target);
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);
}
Destroy();
}
}
@ -100,7 +107,14 @@ Class SilverImpact : Actor
override void PostBeginPlay()
{
Super.PostBeginPlay();
SWWMUtility.DoExplosion(self,100,8000,100,20);
int nhit, nkill;
[nhit, nkill] = SWWMUtility.DoExplosion(self,100,8000,100,20,DE_COUNTENEMIES);
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);
}
A_AlertMonsters(swwm_uncapalert?0:2500);
A_QuakeEx(4,4,4,20,0,400,"",QF_RELATIVE|QF_SCALEDOWN,falloff:100,rollIntensity:.9);
if ( special1 )