More changes from master.

This commit is contained in:
Mari the Deer 2021-09-22 19:39:44 +02:00
commit 9f54ec6f62
22 changed files with 335 additions and 143 deletions

View file

@ -254,7 +254,7 @@ Coming from an old unreleased weapon mini-mod, the **Candy Gun** is like an **Ex
**Reload:** Does what you'd expect.
Holding primary fire during the first few moments of alt fire will throw the weapon itself, armed and ready to explode if it hits anyone or anything. The blast area for this is pretty ridiculous. You can hold spare guns, by the way (up to four).
Holding secondary fire and primary fire (in that order) will throw the weapon itself, armed and ready to explode if it hits anyone or anything. The blast area for this is pretty ridiculous. You can hold spare guns, by the way (up to four).
### Candy Gun Bullets ~ Replaces Cells, Runes
![](docimg/candybullet.png)
@ -393,7 +393,7 @@ Note: In multiplayer, these can be traded between players, but do note that the
### Universal Ammo Fabricator ~ Replaces Mana / Krater of Might
![](docimg/fabricator.png)
Separated into four tiers, they work pretty much like the ammo cubes in **Doom Tournament**, except they try to *"balance"* the total ammo given. The max tier fabricator is the only one capable of producing ammo for superweapons (excluding the **Ynykron Artifact**).
Separated into four tiers, they work pretty much like the ammo cubes in **Doom Tournament**, except they try to *"balance"* the total ammo given. The max tier fabricator is the only one capable of producing ammo for all weapons (excluding the **Ynykron Artifact**). Due to some unspecified reasons, they cannot be held in your inventory.
### Lamp ~ Replaces Lite-Amp, Torch
![](docimg/lamp.png)

View file

@ -408,7 +408,7 @@ SWWM_LORETXT_CANDYGUN =
"\n"
"\cfSecondary Fire:\c- Perform an \"explosive reload\", just like with a standard Explodium Gun. Note that unlike its weaker counterpart, the yield is much more extreme. It is best practice to always have one spare magazine at the ready for the reload, so you aren't left with an unusable weapon should your throw miss the target.\n"
"\n"
"\cfCombo Fire:\c- During the first moments of preparing an explosive reload, you can opt to, instead, leave the magazine in the gun, armed and ready, then throw the whole weapon as a grenade, for the ultimate destruction. As always, make sure you have a fully loaded spare around, or you'll be left with nothing. Due to this disposable nature, you're allowed to carry up to 4 spares in your inventory. Use them well.\n"
"\cfCombo Fire:\c- By holding secondary and primary fire (in that order) you can opt to, instead of performing the usual explosive reload, leave the magazine in the gun, armed and ready, then throw the whole weapon as a grenade, for the ultimate destruction. As always, make sure you at least have a spare and more ammo, or you'll be left with nothing. Due to this disposable nature, you're allowed to carry up to 4 spares in your inventory. Use them well.\n"
"\n"
"\cxSaya's Notes:\c-\n"
"\cfI don't get it, really don't. How is it that mixing that exploding shit with candy does this? Oh, whatever, I still love every second of it, but the pretty fireworks make me really nostalgic, for some reason...\c-\n"

View file

@ -381,7 +381,7 @@ SWWM_LORETXT_CANDYGUN =
"\n"
"\cfFuego Secundario:\c- Realiza una \"recarga explosiva\", al igual que la Pistola de Explodium estándar. Ten en cuenta que a diferencia de su débil homóloga, la carga explosiva es mucho más extrema. Se recomienda tener siempre un cargador de repuesto listo para la recarga, para no acabar con un arma inútil si el que has lanzado no alcanza su objetivo.\n"
"\n"
"\cfFuego Combinado:\c- Durante los primeros momentos de preparar una recarga explosiva, también puedes, en su lugar, dejar el cargador dentro de la pistola, armado y listo, y entonces lanzar el arma entera como una granada, para una destrucción total. Como siempre, asegúrate de tener una de repuesto cargada, o acabarás con las manos vacías. Dada esta naturaleza desechable, se te permite llevar hasta 4 repuestos en tu inventario. Úsalos bien.\n"
"\cfFuego Combinado:\c- Manteniendo el fuego secundario y primario pulsados (en ese orden) puedes optar por, en lugar de realizar la típica recarga explosiva, dejar el cargador dentro de la pistola, armado y listo, y entonces lanzar el arma entera como una granada, para una destrucción total. Como siempre, asegúrate de tener al menos un repuesto y más munición, o acabarás con las manos vacías. Dada esta naturaleza desechable, se te permite llevar hasta 4 repuestos en tu inventario. Úsalos bien.\n"
"\n"
"\cxNotas de Saya:\c-\n"
"\cfNo lo pillo, en serio que no. ¿Como es que mezclando toda esa mierda explosiva con caramelo hace esto? Oh, es igual, me sigue molando mucho cada momento, pero los bonitos fuegos artificiales me dan como nostalgia, no sé por qué...\c-\n"

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\chSWWM \czGZ\c- \cw1.2pre r1 \cu(Mon 20 Sep 23:36:13 CEST 2021)\c-";
SWWM_SHORTVER="\cw1.2pre r1 \cu(2021-09-20 23:36:13)\c-";
SWWM_MODVER="\chSWWM \czGZ\c- \cw1.2pre r2 \cu(Wed 22 Sep 19:39:44 CEST 2021)\c-";
SWWM_SHORTVER="\cw1.2pre r2 \cu(2021-09-22 19:39:44)\c-";

View file

@ -18,7 +18,7 @@ A highly boosted variant of the standard **Explodium Gun**. Its magenta tint com
\cfSecondary Fire:\c- Perform an "explosive reload", just like with a standard Explodium Gun. Note that unlike its weaker counterpart, the yield is much more extreme. It is best practice to always have one spare magazine at the ready for the reload, so you aren't left with an unusable weapon should your throw miss the target.
\cfCombo Fire:\c- During the first moments of preparing an explosive reload, you can opt to, instead, leave the magazine in the gun, armed and ready, then throw the whole weapon as a grenade, for the ultimate destruction. As always, make sure you have a fully loaded spare around, or you'll be left with nothing. Due to this disposable nature, you're allowed to carry up to 4 spares in your inventory. Use them well.
\cfCombo Fire:\c- By holding secondary and primary fire (in that order) you can opt to, instead of performing the usual explosive reload, leave the magazine in the gun, armed and ready, then throw the whole weapon as a grenade, for the ultimate destruction. As always, make sure you at least have a spare and more ammo, or you'll be left with nothing. Due to this disposable nature, you're allowed to carry up to 4 spares in your inventory. Use them well.
\cxSaya's Notes:\c-
\cfI don't get it, really don't. How is it that mixing that exploding shit with candy does this? Oh, whatever, I still love every second of it, but the pretty fireworks make me really nostalgic, for some reason...\c-

View file

@ -14,7 +14,7 @@ Una variante altamente potenciada de la **Pistola de Explodium** estándar. Su c
\cfFuego Secundario:\c- Realiza una "recarga explosiva", al igual que la Pistola de Explodium estándar. Ten en cuenta que a diferencia de su débil homóloga, la carga explosiva es mucho más extrema. Se recomienda tener siempre un cargador de repuesto listo para la recarga, para no acabar con un arma inútil si el que has lanzado no alcanza su objetivo.
\cfFuego Combinado:\c- Durante los primeros momentos de preparar una recarga explosiva, también puedes, en su lugar, dejar el cargador dentro de la pistola, armado y listo, y entonces lanzar el arma entera como una granada, para una destrucción total. Como siempre, asegúrate de tener una de repuesto cargada, o acabarás con las manos vacías. Dada esta naturaleza desechable, se te permite llevar hasta 4 repuestos en tu inventario. Úsalos bien.
\cfFuego Combinado:\c- Manteniendo el fuego secundario y primario pulsados (en ese orden) puedes optar por, en lugar de realizar la típica recarga explosiva, dejar el cargador dentro de la pistola, armado y listo, y entonces lanzar el arma entera como una granada, para una destrucción total. Como siempre, asegúrate de tener al menos un repuesto y más munición, o acabarás con las manos vacías. Dada esta naturaleza desechable, se te permite llevar hasta 4 repuestos en tu inventario. Úsalos bien.
\cxNotas de Saya:\c-
\cfNo lo pillo, en serio que no. ¿Como es que mezclando toda esa mierda explosiva con caramelo hace esto? Oh, es igual, me sigue molando mucho cada momento, pero los bonitos fuegos artificiales me dan como nostalgia, no sé por qué...\c-

View file

@ -196,7 +196,7 @@ Slot 9. Pistol (but very strong).
A tasty treat of sweetness and DEATH. From the lost forever™ Weirdweapons pack.
Primary fire does the thing.
Secondary fire does also the same thing as its slot 2 counterpart.
Holding primary fire after pressing secondary fire will switch to yeeting the
Holding secondary and primary fire (in that order) will switch to yeeting the
entire damn gun, for some absurd reason. It's very effective, though.
Considering that you can dispose of it like that, you can hold some spares.

View file

@ -251,16 +251,91 @@ Class SWWMLevelCompatibility : LevelPostProcessor
SetThingEdNum(0,4206992);
SetThingAngle(0,0);
break;
// Hexen MAP06
case '1B6DF1FD51FDC3D882009D287B5A28C6':
case '65EFFD49449AD3FD32A6EB347C6D923B':
// replace an Icon of the Defender with a Chancebox
SetThingEdNum(193,4206920);
SetThingSkills(193,SKILLS_ALL);
SetThingFlags(193,MTF_SINGLE|MTF_COOPERATIVE);
// replace a Mystic Ambit Incant with a Chancebox
SetThingEdNum(377,4206920);
SetThingSkills(193,SKILLS_ALL);
SetThingFlags(377,MTF_SINGLE|MTF_COOPERATIVE);
SetThingAngle(377,90); // should face north
break;
case 'A3D86F121B41320BFD1EB747D9133EF2':
// replace an Icon of the Defender with a Chancebox
SetThingEdNum(193,4206921);
SetThingSkills(193,SKILLS_ALL);
SetThingFlags(193,MTF_SINGLE|MTF_COOPERATIVE);
// this version doesn't have a Mystic Ambit Incant placed
AddThing(4206921,(-32,-3072,-456),90,SKILLS_ALL,MTF_SINGLE|MTF_COOPERATIVE);
break;
// Hexen MAP11
case 'F8DFDCBAA677F83E2CD2409F5C00505F':
case 'CC90EAF7131A1CA59F8322735C92899C':
case 'B2A1B321E56494081085E51931EB3158':
// replace Mystic Urns with Chanceboxes
SetThingEdNum(62,4206920);
SetThingEdNum(63,4206920);
SetThingEdNum(64,4206920);
SetThingSkills(62,SKILLS_ALL);
SetThingSkills(63,SKILLS_ALL);
SetThingSkills(64,SKILLS_ALL);
SetThingFlags(62,MTF_SINGLE|MTF_COOPERATIVE);
SetThingFlags(63,MTF_SINGLE|MTF_COOPERATIVE);
SetThingFlags(64,MTF_SINGLE|MTF_COOPERATIVE);
SetThingAngle(62,0);
SetThingAngle(63,270);
SetThingAngle(64,180);
break;
// Hexen MAP31
case '4A4436544EBFA930AE3C4C8C2409FD6E':
case 'D48508B92843539B4464235C2B355CC3':
case 'BF9DFE95D9351AA3A65666185BFC921C':
// place 2 Chanceboxes at the final room
AddThing(4206920,(416,-352,0),180,SKILLS_ALL,MTF_SINGLE|MTF_COOPERATIVE);
AddThing(4206920,(544,-352,0),0,SKILLS_ALL,MTF_SINGLE|MTF_COOPERATIVE);
break;
// Hexen MAP26
case '339B4B50B615BE6E1D8454F6C605A97C':
case 'BFDC70A9D445EA5B9010ABB133253D6F':
case '2CF971EECD6B790782DB44B0E917B5B2':
// place 2 Chanceboxes in the central square
AddThing(4206920,(-224,416,-128),270,SKILLS_ALL,MTF_SINGLE|MTF_COOPERATIVE);
AddThing(4206920,(-224,-672,-128),90,SKILLS_ALL,MTF_SINGLE|MTF_COOPERATIVE);
break;
// Hexen MAP39
case '2639C89B8B7052E2CE4CB9CFC63F4C53':
case 'EC5A1B294CC7FB822A6C913F811797C4':
case 'FEA83EE6BCFC899F06CBE394DFBE6707':
// replace Porkalator with a Chancebox
SetThingEdNum(179,4206920);
SetThingSkills(179,SKILLS_ALL);
SetThingFlags(179,MTF_SINGLE|MTF_COOPERATIVE);
SetThingAngle(179,270);
// add two more Chanceboxes near it
AddThing(4206920,(-32,2848,128),270,SKILLS_ALL,MTF_SINGLE|MTF_COOPERATIVE);
AddThing(4206920,(160,2848,128),270,SKILLS_ALL,MTF_SINGLE|MTF_COOPERATIVE);
break;
// Hexen MAP40
case '2A6C4235B942467D25FD50D5B313E67A':
case '1C5DE5A921DEE405E98E7E09D9829387':
case 'EFAFE59092DE5E613562ACF52B86C37F':
// place a final Chancebox behind the player start
AddThing(4206920,(2912,256,-112),180,SKILLS_ALL,MTF_SINGLE|MTF_COOPERATIVE);
break;
// Kinsie's Test Map
case '0EADB2F82732A968B8513E4DC6138439':
case 'D70250F93C6B6072DA39D9672B37F236':
case '959A613006CC3AA912C4A22908B7566A':
// add collectibles
for ( int i=0; i<12; i++ )
AddThing(4206900+i,(1472+64*i,640,0));
AddThing(4206900+i,(1472+64*i,640,0),SKILLS_ALL,MTF_SINGLE|MTF_COOPERATIVE);
// add some chance boxes
for ( int i=0; i<3; i++ )
AddThing(4206920,(3616,1824-64*i,0),180);
AddThing(4206920,(3616,1824-64*i,0),180,SKILLS_ALL,MTF_SINGLE|MTF_COOPERATIVE);
break;
}
switch ( checksum )

View file

@ -112,7 +112,7 @@ extend Class SWWMHandler
if ( e.Damage > s.topdealt ) s.topdealt = e.Damage;
}
SWWMFlyTracker.Track(e.Thing,e.DamageSource);
if ( e.Thing.bBOSS )
if ( e.Thing.bBOSS || e.Thing.FindInventory("BossMarker") )
{
let tk = e.Thing.FindInventory("DeepImpactOnlyToken");
if ( !tk )
@ -141,7 +141,7 @@ extend Class SWWMHandler
{
if ( e.Thing.IsFriend(e.DamageSource) )
lastcombat = AddOneliner("friendhit",1,10);
else if ( (!lastcombat || (gametic > lastcombat+100)) && !Random[DemoLines](0,e.DamageSource.bBOSS?2:4) && !SWWMHDoomHandler.IsCuteGirl(e.DamageSource) ) // [HDoom] don't shout at the girls
else if ( (!lastcombat || (gametic > lastcombat+100)) && !Random[DemoLines](0,(e.DamageSource.bBOSS||e.DamageSource.FindInventory("BossMarker"))?2:4) && !SWWMHDoomHandler.IsCuteGirl(e.DamageSource) ) // [HDoom] don't shout at the girls
lastcombat = AddOneliner("gethit",1,15);
}
highesttic = gametic;
@ -180,7 +180,7 @@ extend Class SWWMHandler
{
if ( e.Thing.IsFriend(src) )
lastcombat = AddOneliner("friendkill",1,5);
else if ( (!lastcombat || (gametic > lastcombat+100)) && !Random[DemoLines](0,e.Thing.bBOSS?2:5) && !SWWMHDoomHandler.IsCuteGirl(e.Thing) ) // [HDoom] don't shout at the girls
else if ( (!lastcombat || (gametic > lastcombat+100)) && !Random[DemoLines](0,(e.Thing.bBOSS||e.Thing.FindInventory("BossMarker"))?2:5) && !SWWMHDoomHandler.IsCuteGirl(e.Thing) ) // [HDoom] don't shout at the girls
lastcombat = AddOneliner("scorekill",1,15);
}
}
@ -188,7 +188,7 @@ extend Class SWWMHandler
// achievement stuff
if ( e.Thing.IsHostile(src) )
{
if ( e.Thing.bBOSS && ((e.DamageType == 'Dash') || (e.DamageType == 'Buttslam')) )
if ( (e.Thing.bBOSS||e.Thing.FindInventory("BossMarker")) && ((e.DamageType == 'Dash') || (e.DamageType == 'Buttslam')) )
SWWMUtility.AchievementProgressInc("bossdash",1,src.player);
if ( e.DamageType == 'Push' )
SWWMUtility.AchievementProgressInc("sneeze",1,src.player);
@ -334,7 +334,7 @@ extend Class SWWMHandler
scr.xcnt = ++ofs;
}
}
if ( e.Thing.bBOSS )
if ( e.Thing.bBOSS || e.Thing.FindInventory("BossMarker") )
{
score += 2000;
if ( scr )

View file

@ -1,6 +1,7 @@
// vanilla boss stuff
Class EndgameBossMarker : Inventory {}
Class BossMarker : Inventory {}
extend Class SWWMHandler
{
@ -116,6 +117,7 @@ extend Class SWWMHandler
bossactors.Push(e.Thing);
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 3;
if ( trk ) trk.bBOSS = true;
e.Thing.GiveInventory('BossMarker',1);
}
bosstag = "$BT_BRUISERS";
}
@ -126,6 +128,7 @@ extend Class SWWMHandler
bossactors.Push(e.Thing);
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 5;
if ( trk ) trk.bBOSS = true;
e.Thing.GiveInventory('BossMarker',1);
}
bosstag = "$BT_CYBIE";
}
@ -136,6 +139,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('BossMarker',1);
e.Thing.GiveInventory('EndgameBossMarker',1);
}
bosstag = "$BT_SPIDER";
@ -147,6 +151,7 @@ extend Class SWWMHandler
bossactors.Push(e.Thing);
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 4;
if ( trk ) trk.bBOSS = true;
e.Thing.GiveInventory('BossMarker',1);
}
bosstag = "$BT_SPIDER2";
}
@ -157,6 +162,7 @@ extend Class SWWMHandler
bossactors.Push(e.Thing);
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 2;
if ( trk ) trk.bBOSS = true;
e.Thing.GiveInventory('BossMarker',1);
}
bosstag = "$BT_DIMPLE";
}
@ -168,6 +174,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('BossMarker',1);
e.Thing.GiveInventory('EndgameBossMarker',1);
}
if ( e.Thing is 'BossEye' )
@ -181,6 +188,7 @@ extend Class SWWMHandler
bossactors.Push(e.Thing);
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 4;
if ( trk ) trk.bBOSS = true;
e.Thing.GiveInventory('BossMarker',1);
}
bosstag = "$BT_CYBIE2";
}
@ -191,6 +199,7 @@ extend Class SWWMHandler
bossactors.Push(e.Thing);
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 4;
if ( trk ) trk.bBOSS = true;
e.Thing.GiveInventory('BossMarker',1);
}
bosstag = "$BT_LICHES";
}
@ -201,6 +210,7 @@ extend Class SWWMHandler
bossactors.Push(e.Thing);
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 3;
if ( trk ) trk.bBOSS = true;
e.Thing.GiveInventory('BossMarker',1);
}
bosstag = "$BT_MINOTAUR";
}
@ -212,6 +222,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 2;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_DSPARIL";
e.Thing.GiveInventory('BossMarker',1);
e.Thing.GiveInventory('EndgameBossMarker',1);
}
else if ( e.Thing is 'Sorcerer2' )
@ -223,6 +234,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 8;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_DSPARIL2";
e.Thing.GiveInventory('BossMarker',1);
e.Thing.GiveInventory('EndgameBossMarker',1);
}
}
@ -234,6 +246,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 2;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_CLERIC";
e.Thing.GiveInventory('BossMarker',1);
}
}
else if ( bossmap == MAP_HMAP36 )
@ -244,6 +257,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 2;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_FIGHTER";
e.Thing.GiveInventory('BossMarker',1);
}
}
else if ( bossmap == MAP_HMAP37 )
@ -254,6 +268,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 2;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_MAGE";
e.Thing.GiveInventory('BossMarker',1);
}
}
else if ( bossmap == MAP_HMAP12 )
@ -264,6 +279,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 4;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_DRAGON";
e.Thing.GiveInventory('BossMarker',1);
}
}
else if ( bossmap == MAP_HMAP23_HMAP27_HMAP48_HMAP55 )
@ -274,6 +290,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 8;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_HERESIARCH";
e.Thing.GiveInventory('BossMarker',1);
}
}
else if ( bossmap == MAP_HMAP40 )
@ -284,6 +301,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 10;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_KORAX";
e.Thing.GiveInventory('BossMarker',1);
e.Thing.GiveInventory('EndgameBossMarker',1);
}
}
@ -296,6 +314,7 @@ extend Class SWWMHandler
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_DEATHKINGS";
initialized = true; // healthbar shows from the start
e.Thing.GiveInventory('BossMarker',1);
e.Thing.GiveInventory('EndgameBossMarker',1);
}
}
@ -307,6 +326,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 5;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_ARCHANGELUS";
e.Thing.GiveInventory('BossMarker',1);
e.Thing.GiveInventory('EndgameBossMarker',1);
}
else if ( e.Thing.GetClassName() == "ArchangelusB" )
@ -318,6 +338,7 @@ extend Class SWWMHandler
if ( upgrademe ) e.Thing.StartHealth = e.Thing.Health *= 5;
if ( trk ) trk.bBOSS = true;
bosstag = "$BT_ARCHANGELUS";
e.Thing.GiveInventory('BossMarker',1);
e.Thing.GiveInventory('EndgameBossMarker',1);
doextramsg = true;
}

View file

@ -65,10 +65,12 @@ extend Class SWWMHandler
int csiz = s.clustervisit.Size();
if ( csiz == 0 )
{
s.clustervisit.Push(clust);
s.secretdone.Push(secret);
}
else if ( s.clustervisit[csiz-1] != clust )
{
s.clustervisit.Push(clust);
s.secretdone.Push(secret|s.secretdone[csiz-1]);
}
s.AddLevelStats();

View file

@ -77,7 +77,7 @@ extend Class SWWMHandler
override void WorldThingDied( WorldEvent e )
{
if ( profiling ) curms = MSTime();
if ( e.Thing.default.bISMONSTER && ((e.Thing.default.bBOSS) || (e.Thing.GetSpawnHealth() >= 1000)) && (alreadygold.Find(e.Thing) == alreadygold.Size()) )
if ( e.Thing.default.bISMONSTER && ((e.Thing.default.bBOSS) || (e.Thing.GetSpawnHealth() >= 1000) || e.Thing.FindInventory("BossMarker")) && (alreadygold.Find(e.Thing) == alreadygold.Size()) )
{
// make sure we can't farm drops from revivable enemies
// (or cause some things to spam-spawn gold shells)

View file

@ -251,7 +251,7 @@ extend Class SWWMHandler
continue;
if ( !thesight && !(deathmatch && (a is 'Inventory') && !a.bDROPPED) && !(a.IsFriend(players[consoleplayer].mo) && !(a.player && (a.player.mo != a))) && !players[consoleplayer].Camera.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
continue;
if ( a.bKILLED || (a.Health <= 0) )
if ( a.bKILLED || (a.Health <= 0) || a.bUnmorphed )
continue;
if ( (a is 'Inventory') && (!a.bSPECIAL || Inventory(a).Owner) )
continue;
@ -307,7 +307,7 @@ extend Class SWWMHandler
continue;
if ( !thesight && !(deathmatch && (a is 'Inventory') && !a.bDROPPED) && !a.IsFriend(players[consoleplayer].mo) && !players[consoleplayer].Camera.CheckSight(a,SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) )
continue;
if ( a.bKILLED || (a.Health <= 0) )
if ( a.bKILLED || (a.Health <= 0) || a.bUnmorphed )
continue;
if ( (a is 'Inventory') && (!a.bSPECIAL || Inventory(a).Owner) )
continue;
@ -353,7 +353,8 @@ extend Class SWWMHandler
if ( (trk.target.bKILLED || (trk.target.Health <= 0))
|| ((trk.target is 'Inventory') && (!trk.target.bSPECIAL || Inventory(trk.target).Owner))
|| ((trk.target is 'Chancebox') && (trk.target.CurState != trk.target.SpawnState))
|| (trk.target.default.bMISSILE && !trk.target.bMISSILE) )
|| (trk.target.default.bMISSILE && !trk.target.bMISSILE)
|| trk.target.bUnmorphed )
trk.Update();
}
// prune expired trackers

View file

@ -9,11 +9,18 @@ Class AmmoFabricator : Inventory abstract
Mixin SWWMRespawn;
Mixin SWWMPickupGlow;
int budget, pertype, maxunitprice;
int budget, pertype, maxunits, maxtypes, maxunitprice, txtcol;
int chancediv;
String pickupmsgextra;
Property Budget : budget;
Property PerType : pertype;
Property MaxUnits : maxunits;
Property MaxTypes : maxtypes;
Property MaxUnitPrice : maxunitprice;
Property ChanceFactor : chancediv;
Property TextColor : txtcol;
override Inventory CreateCopy( Actor other )
{
@ -22,7 +29,7 @@ Class AmmoFabricator : Inventory abstract
return Super.CreateCopy(other);
}
private bool CmpFabAmmo( Class<Ammo> a, Class<Ammo> b )
private bool CmpFabAmmo( Class<SWWMAmmo> a, Class<SWWMAmmo> b )
{
let ia = Owner.FindInventory(a);
int cnta = ia?ia.Amount:0;
@ -35,26 +42,26 @@ Class AmmoFabricator : Inventory abstract
return (facta >= factb);
}
private int partition_fabammo( Array<Class<Ammo> > a, int l, int h )
private int partition_fabammo( Array<Class<SWWMAmmo> > a, int l, int h )
{
Class<Ammo> pv = a[h];
Class<SWWMAmmo> pv = a[h];
int i = (l-1);
for ( int j=l; j<=(h-1); j++ )
{
if ( CmpFabAmmo(pv,a[j]) )
{
i++;
Class<Ammo> tmp = a[j];
Class<SWWMAmmo> tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}
}
Class<Ammo> tmp = a[h];
Class<SWWMAmmo> tmp = a[h];
a[h] = a[i+1];
a[i+1] = tmp;
return i+1;
}
private void qsort_fabammo( Array<Class<Ammo> > a, int l, int h )
private void qsort_fabammo( Array<Class<SWWMAmmo> > a, int l, int h )
{
if ( l >= h ) return;
int p = partition_fabammo(a,l,h);
@ -62,6 +69,46 @@ Class AmmoFabricator : Inventory abstract
qsort_fabammo(a,p+1,h);
}
private bool CmpFabAmmo_chance( Class<SWWMAmmo> a, Class<SWWMAmmo> b )
{
int cha = GetDefaultByType(a).Accuracy;
int chb = GetDefaultByType(b).Accuracy;
return (cha >= chb);
}
private int partition_fabammo_chance( Array<Class<SWWMAmmo> > a, int l, int h )
{
Class<SWWMAmmo> pv = a[h];
int i = (l-1);
for ( int j=l; j<=(h-1); j++ )
{
if ( CmpFabAmmo_chance(pv,a[j]) )
{
i++;
Class<SWWMAmmo> tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}
}
Class<SWWMAmmo> tmp = a[h];
a[h] = a[i+1];
a[i+1] = tmp;
return i+1;
}
private void qsort_fabammo_chance( Array<Class<SWWMAmmo> > a, int l, int h )
{
if ( l >= h ) return;
int p = partition_fabammo_chance(a,l,h);
qsort_fabammo_chance(a,l,p-1);
qsort_fabammo_chance(a,p+1,h);
}
override String PickupMessage()
{
if ( pickupmsgextra != "" ) return String.Format("\c%c%s\c-\n%s",0x61+txtcol,StringTable.Localize(pickupmsg),pickupmsgextra);
return pickupmsg;
}
bool FabricateAmmo()
{
// first we must build an array of all valid weapons, this saves time instead of doing recursive loops
@ -78,11 +125,11 @@ Class AmmoFabricator : Inventory abstract
if ( !ready || !ready.ValidateSpriteFrame() ) continue;
validweapons.Push(type2);
}
Array<Class<Ammo> > available;
Array<Class<SWWMAmmo> > available;
// populate ammo production list
for ( int i=0; i<AllActorClasses.Size(); i++ )
{
let a = (Class<Ammo>)(AllActorClasses[i]);
let a = (Class<SWWMAmmo>)(AllActorClasses[i]);
// skip over candy gun spares, they're "special ammo"
if ( a == 'CandyGunSpares' ) continue;
// only direct descendants of swwmammo with a set price below our max unit price
@ -106,21 +153,40 @@ Class AmmoFabricator : Inventory abstract
}
}
if ( !isvalid ) continue;
let f = Owner.FindInventory(a);
// don't include maxed out ammo
if ( f && (f.Amount >= f.MaxAmount) ) continue;
available.Push(a);
}
// sort by "need weight" (prioritize ammo that the player lacks over ammo that the player has plenty of
// sort by drop chance
qsort_fabammo_chance(available,0,available.Size()-1);
// discard some candidates based on their random drop chance (leaving AT LEAST one)
for ( int i=0; i<available.Size(); i++ )
{
if ( available.Size() == 1 ) break;
int chance = GetDefaultByType(available[i]).Accuracy;
if ( chancediv <= 0 ) chance = 0;
else chance /= chancediv;
if ( Random[DropChance](1,100) > chance ) continue;
available.Delete(i);
i--;
}
// sort by "need weight" (prioritize ammo that the player lacks over ammo that the player has plenty of)
qsort_fabammo(available,0,available.Size()-1);
// crop by "max types"
if ( available.Size() > maxtypes ) available.Resize(maxtypes);
// loop through until we fill the inventory or run out of budget
bool given = false;
int consumed = 0;
String fabstr = "";
bool comma = false;
int tpertype = pertype;
int ttotal = maxunits;
for ( int i=0; i<available.Size(); i++ )
{
int amt, lim;
int cnt = 0;
Ammo cur = Ammo(Owner.FindInventory(available[i]));
SWWMAmmo cur = SWWMAmmo(Owner.FindInventory(available[i]));
if ( cur )
{
amt = cur.Amount;
@ -128,13 +194,14 @@ Class AmmoFabricator : Inventory abstract
}
else
{
cur = Ammo(Spawn(available[i]));
cur = SWWMAmmo(Spawn(available[i]));
amt = cur.Amount = 0;
lim = cur.MaxAmount;
cur.AttachToOwner(Owner);
}
// percentage based on DEFAULT max amount (capped at 1 minimum)
if ( pertype < 0 ) tpertype = max(1,-int(cur.default.MaxAmount*pertype*.01));
tpertype = min(tpertype,ttotal);
while ( (amt < lim) && (consumed+cur.default.Stamina < budget) && (cnt < tpertype) )
{
consumed += cur.default.Stamina;
@ -144,68 +211,21 @@ Class AmmoFabricator : Inventory abstract
}
if ( cnt > 0 )
{
if ( comma ) fabstr.AppendFormat(", %dx %s",cnt,cur.GetTag());
else fabstr.AppendFormat("%dx %s",cnt,cur.GetTag());
String tstr = String.Format("%d %s",cnt,(cnt>1)?StringTable.Localize("$T_"..cur.PickupTag.."S"):StringTable.Localize("$T_"..cur.PickupTag));
if ( comma ) fabstr = fabstr..", "..tstr;
else fabstr = tstr;
comma = true;
}
ttotal -= cnt;
if ( ttotal <= 0 ) break;
}
if ( given ) PrintPickupMessage(true,fabstr);
if ( given ) pickupmsgextra = fabstr;
else pickupmsgextra = "";
return given;
}
override void DoEffect()
{
Super.DoEffect();
if ( !Owner || !bAUTOACTIVATE ) return;
bool shouldautouse = false;
if ( swwm_enforceautouseammo == 1 ) shouldautouse = true;
else if ( swwm_enforceautouseammo == -1 ) shouldautouse = false;
else shouldautouse = CVar.GetCVar('swwm_autouseammo',Owner.player).GetBool();
if ( !shouldautouse ) return;
// fabricators of lower tiers, for priority checking
Array<AmmoFabricator> others;
for ( Inventory i=Owner.inv; i; i=i.inv )
{
if ( !(i is 'AmmoFabricator') || (i == self) || !i.bAUTOACTIVATE || (AmmoFabricator(i).maxunitprice >= maxunitprice) ) continue;
others.Push(AmmoFabricator(i));
}
// check if owner lacks ammo, autouse if we can afford its unit price
bool used = false;
Actor o = Owner;
for ( Inventory i=o.inv; i; i=i.inv )
{
if ( !(i is 'Ammo') || (i.Amount > (i.MaxAmount/3)) || (i.Stamina <= 0) || (i.Stamina > maxunitprice) ) continue;
// ignore if there's a cheaper fabricator than us that can afford it ("wait our turn", basically)
bool lowprio = false;
for ( int j=0; j<others.Size(); j++ )
{
if ( i.Stamina > others[j].maxunitprice ) continue;
lowprio = true;
break;
}
if ( lowprio ) continue;
// hit it
while ( (Amount > 0) && FabricateAmmo() )
{
used = true;
Amount--;
}
if ( Amount <= 0 )
{
DepleteOrDestroy();
break;
}
}
if ( used && (o.player == players[consoleplayer]) ) o.A_StartSound(UseSound,CHAN_ITEMEXTRA);
}
override bool Use( bool pickup )
{
bool shouldautouse = false;
if ( swwm_enforceautouseammo == 1 ) shouldautouse = true;
else if ( swwm_enforceautouseammo == -1 ) shouldautouse = false;
else shouldautouse = CVar.GetCVar('swwm_autouseammo',Owner.player).GetBool();
if ( pickup && !shouldautouse ) return false;
if ( FabricateAmmo() )
{
if ( pickup && ((Owner.player == players[consoleplayer]) || bBigPowerup) ) Owner.A_StartSound(UseSound,CHAN_ITEMEXTRA);
@ -214,13 +234,19 @@ Class AmmoFabricator : Inventory abstract
return false;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
SetZ(floorz); // gee whizz thanks Hexen
}
Default
{
+INVENTORY.INVBAR;
+INVENTORY.AUTOACTIVATE;
+FLOATBOB;
Inventory.UseSound "fabricator/use";
Inventory.PickupFlash "SWWMPickupFlash";
Inventory.MaxAmount 0;
FloatBobStrength 0.25;
Radius 10;
Height 24;
@ -244,14 +270,15 @@ Class FabricatorTier1 : AmmoFabricator
//$Sprite graphics/HUD/Icons/I_Fabricator1.png
//$Icon ammo
Tag "$T_FABRICATOR1";
Stamina -2500;
Inventory.Icon "graphics/HUD/Icons/I_Fabricator1.png";
Inventory.PickupMessage "$T_FABRICATOR1";
Inventory.MaxAmount 20;
Inventory.InterHubAmount 20;
AmmoFabricator.Budget 3000;
AmmoFabricator.PerType 1;
AmmoFabricator.MaxUnits 1;
AmmoFabricator.MaxTypes 1;
AmmoFabricator.MaxUnitPrice 2500;
AmmoFabricator.ChanceFactor 1;
AmmoFabricator.TextColor Font.CR_BLUE;
}
}
Class FabricatorTier2 : AmmoFabricator
@ -265,14 +292,15 @@ Class FabricatorTier2 : AmmoFabricator
//$Sprite graphics/HUD/Icons/I_Fabricator2.png
//$Icon ammo
Tag "$T_FABRICATOR2";
Stamina -12000;
Inventory.Icon "graphics/HUD/Icons/I_Fabricator2.png";
Inventory.PickupMessage "$T_FABRICATOR2";
Inventory.MaxAmount 15;
Inventory.InterHubAmount 15;
AmmoFabricator.Budget 15000;
AmmoFabricator.PerType 2;
AmmoFabricator.MaxUnitPrice 12000;
AmmoFabricator.Budget 20000;
AmmoFabricator.PerType 1;
AmmoFabricator.MaxUnits 2;
AmmoFabricator.MaxTypes 2;
AmmoFabricator.MaxUnitPrice 18000;
AmmoFabricator.ChanceFactor 2;
AmmoFabricator.TextColor Font.CR_GREEN;
}
}
Class FabricatorTier3 : AmmoFabricator
@ -286,18 +314,21 @@ Class FabricatorTier3 : AmmoFabricator
//$Sprite graphics/HUD/Icons/I_Fabricator3.png
//$Icon ammo
Tag "$T_FABRICATOR3";
Stamina -80000;
Inventory.Icon "graphics/HUD/Icons/I_Fabricator3.png";
Inventory.PickupMessage "$T_FABRICATOR3";
Inventory.MaxAmount 10;
Inventory.InterHubAmount 10;
AmmoFabricator.Budget 100000;
AmmoFabricator.PerType 4;
AmmoFabricator.PerType 2;
AmmoFabricator.MaxUnits 4;
AmmoFabricator.MaxTypes 3;
AmmoFabricator.MaxUnitPrice 80000;
AmmoFabricator.ChanceFactor 4;
AmmoFabricator.TextColor Font.CR_RED;
}
}
Class FabricatorTier4 : AmmoFabricator
{
Mixin SWWMAutoUseFix;
Default
{
//$Title Fabricator (Super Rare)
@ -305,15 +336,15 @@ Class FabricatorTier4 : AmmoFabricator
//$Sprite graphics/HUD/Icons/I_Fabricator4.png
//$Icon ammo
Tag "$T_FABRICATOR4";
Stamina -1000000;
Inventory.Icon "graphics/HUD/Icons/I_Fabricator4.png";
Inventory.PickupMessage "$T_FABRICATOR4";
Inventory.MaxAmount 5;
Inventory.InterHubAmount 5;
AmmoFabricator.Budget int.max;
AmmoFabricator.PerType -50;
AmmoFabricator.MaxUnits int.max;
AmmoFabricator.MaxTypes int.max;
AmmoFabricator.MaxUnitPrice 1000000;
-INVENTORY.AUTOACTIVATE;
AmmoFabricator.ChanceFactor 0;
AmmoFabricator.TextColor Font.CR_GOLD;
}
}

View file

@ -2345,7 +2345,7 @@ Class MykradvoTendril : Actor
{
if ( t.hitlist[i].hitactor.IsFriend(target) ) continue;
if ( (t.hitlist[i].hitactor == tracer) && bMISSILEMORE ) bMISSILEEVENMORE = true; // we split
int dmg = t.hitlist[i].hitactor.bBOSS?(GetMissileDamage(0,0)*4):max(t.hitlist[i].hitactor.Health,GetMissileDamage(0,0));
int dmg = (t.hitlist[i].hitactor.bBOSS||t.hitlist[i].hitactor.FindInventory("BossMarker"))?(GetMissileDamage(0,0)*4):max(t.hitlist[i].hitactor.Health,GetMissileDamage(0,0));
SWWMUtility.DoKnockback(t.hitlist[i].hitactor,-t.hitlist[i].x+(0,0,.5),((t.hitlist[i].hitactor.Health-dmg)<=0)?60000:8000);
t.hitlist[i].hitactor.DamageMobj(self,target,dmg,'Plasma',DMG_THRUSTLESS);
if ( t.hitlist[i].hitactor && t.hitlist[i].hitactor.bISMONSTER && !Random[Mykradvo](0,3) )
@ -2353,7 +2353,7 @@ Class MykradvoTendril : Actor
}
}
invoker.nextpos = level.Vec3Offset(pos,x*speed);
if ( !bSTANDSTILL && (!tracer || !tracer.bSHOOTABLE || (tracer.Health <= 0) || (tracer.bBOSS && !bMISSILEMORE)) )
if ( !bSTANDSTILL && (!tracer || !tracer.bSHOOTABLE || (tracer.Health <= 0) || ((tracer.bBOSS || tracer.FindInventory("BossMarker")) && !bMISSILEMORE)) )
{
ReactionTime--;
if ( ReactionTime <= 0 )
@ -2396,7 +2396,7 @@ Class MykradvoTendril : Actor
r.pitch = asin(-sdir.z);
r.target = target;
r.tracer = tracer;
if ( tracer && tracer.bBOSS ) r.ReactionTime -= Random[ExploS](5,15);
if ( tracer && (tracer.bBOSS || tracer.FindInventory("BossMarker")) ) r.ReactionTime -= Random[ExploS](5,15);
else r.ReactionTime += Random[ExploS](0,20);
}
return;
@ -2850,7 +2850,7 @@ Class Mykradvo : Inventory
Amount++;
return true;
}
if ( (targets.Size() == 1) && targets[0] && !targets[0].bBOSS )
if ( (targets.Size() == 1) && targets[0] && !targets[0].bBOSS && !targets[0].FindInventory("BossMarker") )
SWWMUtility.MarkAchievement("anone",Owner.player);
let p = Spawn("MykradvoBurst",spawnpos);
p.target = Owner;
@ -3500,7 +3500,6 @@ Class DivineSpriteEffect : Inventory
{
Inventory.Icon "graphics/HUD/Icons/I_Divine.png";
DivineSpriteEffect.HealTimer 1750;
Inventory.InterHubAmount 0;
+INVENTORY.UNDROPPABLE;
+INVENTORY.UNTOSSABLE;
}
@ -3518,6 +3517,12 @@ Class DivineSpriteEffect : Inventory
return Color(int(64*alph),255,255,255);
}
override void Travelled()
{
Super.Travelled();
bHealDone = true;
}
override void DoEffect()
{
Super.DoEffect();

View file

@ -896,7 +896,7 @@ Class Demolitionist : PlayerPawn
if ( player.onground && (player.jumptics < -18) )
player.jumptics = 0;
}
if ( player.playerstate != PST_DEAD )
if ( (player.playerstate != PST_DEAD) && !ReactionTime )
{
// quick grenade
if ( player.cmd.buttons&BT_USER4 )

View file

@ -285,6 +285,8 @@ Class SWWMCombatTracker : Thinker
int mxdist, dbar;
bool bBOSS, bFRIENDLY;
bool firsthit;
bool bUpdateMorph;
String unmorphedtag;
void UpdateTag()
{
@ -405,6 +407,12 @@ Class SWWMCombatTracker : Thinker
pos = level.Vec3Offset(mytarget.pos,(0,0,height));
prevpos = level.Vec3Offset(mytarget.prev,(0,0,height));
}
if ( bUpdateMorph && !(mytarget is 'MorphedMonster') )
{
// reset our tag
mytag = unmorphedtag;
bUpdateMorph = false;
}
tcnt++;
if ( (tcnt == 1) && !mytarget.player )
{
@ -414,6 +422,21 @@ Class SWWMCombatTracker : Thinker
maxhealth = lasthealth;
intp.Reset(lasthealth);
}
// post-spawn morph check
if ( (mytarget is 'MorphedMonster') && MorphedMonster(mytarget).UnmorphedMe )
{
// look for a previous tracker that has the same target as us
for ( SWWMCombatTracker t=next; t; t=t.next )
{
if ( t.mytarget != mytarget ) continue;
// change its tag and destroy ourselves (such is life)
t.bUpdateMorph = true;
t.unmorphedtag = t.mytag;
t.mytag = String.Format("%s (%s)",mytag,t.unmorphedtag);
Destroy();
return;
}
}
}
if ( (tcnt == 6) && !mytarget.player )
{
@ -547,7 +570,7 @@ Class SWWMSimpleTracker : Thinker
}
else if ( ismonster )
{
expired = target.bKILLED;
expired = target.bKILLED||target.bUnmorphed;
if ( !expired )
{
lastupdate += 35;

View file

@ -518,7 +518,7 @@ Class YnykronImpact : Actor
if ( t && YnykronShot(master) )
{
YnykronShot(master).hitlist.Push(t);
if ( t.bBOSS ) YnykronShot(master).hitboss = true;
if ( t.bBOSS || t.FindInventory("BossMarker") ) YnykronShot(master).hitboss = true;
}
// spawn blast that will propagate
let b = Spawn("YnykronDelayedImpact",t.pos);
@ -705,7 +705,7 @@ Class YnykronBeam : Actor
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;
if ( t.hitlist[i].hitactor.bBOSS || t.hitlist[i].hitactor.FindInventory("BossMarker") ) YnykronShot(master).hitboss = true;
}
// spawn blast that will propagate
let b = Spawn("YnykronImpact",t.hitlist[i].hitlocation);
@ -805,7 +805,7 @@ Class YnykronBeam : Actor
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;
if ( it.hitlist[i].hitactor.bBOSS || it.hitlist[i].hitactor.FindInventory("BossMarker") ) YnykronShot(master).hitboss = true;
}
// spawn blast that will propagate
let b = Spawn("YnykronImpact",it.hitlist[i].hitlocation);

View file

@ -24,7 +24,7 @@ Class AirBullet : FastProjectile
}
override int DoSpecialDamage( Actor target, int damage, Name damagetype )
{
if ( target.bBOSS ) damage = int(damage*.4);
if ( target.bBOSS || target.FindInventory("BossMarker") ) damage = int(damage*.4);
if ( !bAMBUSH )
{
if ( target == lasthit ) return 0;

View file

@ -185,6 +185,7 @@ Class PusherWeapon : SWWMWeapon
{
// didn't hit anything, randomly slip off
player.SetPSprite(PSP_WEAPON,ResolveState("AltMiss"));
invoker.bNODEATHDESELECT = true; // prevent any glitching that could happen if the sequence is interrupted
A_StopSound(CHAN_WEAPON);
A_StopSound(CHAN_WEAPONEXTRA);
A_StartSound("pusher/miss",CHAN_WEAPON,CHANF_OVERLAP);
@ -357,18 +358,16 @@ Class PusherWeapon : SWWMWeapon
XZW3 QRSTUVW 1;
TNT1 A -1
{
if ( player.PendingWeapon != WP_NOCHANGE )
invoker.bNODEATHDESELECT = false;
let nw = player.mo.PickNextWeapon();
// gross hack (don't prioritize Deep Impact if we have something better than it)
if ( nw is 'DeepImpact' )
{
let nw = player.mo.PickNextWeapon();
// gross hack (don't prioritize Deep Impact if we have something better than it)
if ( nw is 'DeepImpact' )
{
player.ReadyWeapon = nw;
nw = player.mo.PickNextWeapon();
player.ReadyWeapon = invoker;
}
if ( nw != invoker ) player.PendingWeapon = nw;
player.ReadyWeapon = nw;
nw = player.mo.PickNextWeapon();
player.ReadyWeapon = invoker;
}
if ( nw != invoker ) player.PendingWeapon = nw;
RemoveInventory(invoker);
invoker.Destroy();
}

View file

@ -1220,7 +1220,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 )
if ( crit && victim && (victim.Health <= 0) && (victim.bBOSS || victim.FindInventory("BossMarker")) && target )
SWWMUtility.MarkAchievement("clonk",target.player);
// only rip shootables
if ( (slamforce > girth) && is_schutt )

View file

@ -85,6 +85,7 @@ Class CandyGun : SWWMWeapon
override void DrawWeapon( double TicFrac, double bx, double by, Vector2 hs, Vector2 ss )
{
if ( Amount <= 0 ) return;
if ( !WeaponBox ) WeaponBox = TexMan.CheckForTexture("graphics/HUD/CandygunDisplay.png",TexMan.Type_Any);
if ( !TewiFont ) TewiFont = Font.GetFont('TewiShaded');
Screen.DrawTexture(WeaponBox,false,bx-51,by-44,DTA_VirtualWidthF,ss.x,DTA_VirtualHeightF,ss.y,DTA_KeepRatio,true);
@ -215,8 +216,12 @@ Class CandyGun : SWWMWeapon
{
let weap = Weapon(invoker);
if ( !weap ) return;
invoker.bNODEATHDESELECT = true; // prevent any glitching that could happen if the sequence is interrupted
if ( !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) )
{
if ( weap.Ammo2.Amount <= 0 ) weap.Amount = 0;
weap.Ammo2.Amount = max(0,weap.Ammo2.Amount-1);
}
Vector3 x, y, z, x2, y2, z2;
[x, y, z] = swwm_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x-2*y-3*z);
@ -287,6 +292,7 @@ Class CandyGun : SWWMWeapon
override bool CheckAmmo( int fireMode, bool autoSwitch, bool requireAmmo, int ammocount )
{
if ( sv_infiniteammo || Owner.FindInventory('PowerInfiniteAmmo',true) ) return true;
if ( Amount <= 0 ) return false;
if ( fireMode == PrimaryFire ) return (chambered || (clipcount > 0) || (Ammo1.Amount > 0) || (Owner.CountInv("CandyGunBullets") > 0));
if ( fireMode == AltFire ) return ((Ammo1.Amount > 0) || (Owner.CountInv("CandyGunBullets") > 0));
return Super.CheckAmmo(firemode,autoswitch,requireammo,ammocount);
@ -294,6 +300,7 @@ Class CandyGun : SWWMWeapon
override bool ReportHUDAmmo()
{
if ( Amount <= 0 ) return false;
if ( chambered || (clipcount > 0) || (Owner.CountInv("CandyGunBullets") > 0) ) return true;
if ( Ammo1.Amount <= 0 ) return false;
return Super.ReportHUDAmmo();
@ -388,9 +395,14 @@ Class CandyGun : SWWMWeapon
int flg = WRF_ALLOWZOOM|WRF_ALLOWUSER1;
if ( sv_infiniteammo || FindInventory('PowerInfiniteAmmo',true) || (invoker.Ammo1.Amount > 0) || invoker.chambered ) flg |= WRF_ALLOWRELOAD;
if ( (invoker.Ammo1.Amount <= 0) && (CountInv("CandyGunBullets") <= 0) && !sv_infiniteammo && !FindInventory('PowerInfiniteAmmo',true) ) flg |= WRF_NOSECONDARY;
A_WeaponReady(flg);
if ( player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK) )
invoker.CheckAmmo(EitherFire,true);
if ( (flg&WRF_NOSECONDARY) && (player.cmd.buttons&BT_ATTACK) && (player.cmd.buttons&BT_ALTATTACK) )
player.SetPSprite(PSP_WEAPON,ResolveState("SpecialFirePre"));
else
{
A_WeaponReady(flg);
if ( player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK) )
invoker.CheckAmmo(EitherFire,true);
}
}
}
Wait;
@ -500,7 +512,7 @@ Class CandyGun : SWWMWeapon
XZW5 Q 1;
XZW5 R 1
{
if ( player.cmd.buttons&BT_ATTACK && ((((invoker.Ammo1.Amount > 0) || (CountInv("CandyGunBullets") > 0)) && (invoker.Ammo2.Amount > 0)) || sv_infiniteammo || FindInventory('PowerInfiniteAmmo',true)) )
if ( player.cmd.buttons&BT_ATTACK )
player.SetPSprite(PSP_WEAPON,ResolveState("SpecialFire"));
}
XZW5 STUVWXYZ 1;
@ -527,6 +539,12 @@ Class CandyGun : SWWMWeapon
XZW6 XY 2;
XZW6 Z 4;
Goto ReloadEnd;
SpecialFirePre:
XZW2 A 2 A_PlayerReload();
XZW5 NO 2;
XZW5 P 1 A_StartSound("explodium/magpin",CHAN_WEAPON,CHANF_OVERLAP);
XZW5 QR 1;
Goto SpecialFire+1;
SpecialFire:
#### # 1;
XZWA Z 1;
@ -539,25 +557,42 @@ Class CandyGun : SWWMWeapon
XZWB EFGHIJKLMNOPQR 1;
XZWB S 1 A_ThrowGun();
XZWB TUVWXYZ 2;
XZW1 B 0
XZW1 B -1
{
invoker.PlayUpSound(self);
if ( sv_infiniteammo || FindInventory('PowerInfiniteAmmo',true) )
invoker.clipcount = invoker.default.clipcount;
else if ( invoker.Ammo1.Amount <= 0 )
invoker.bNODEATHDESELECT = false;
if ( (invoker.Amount > 0) && (invoker.Ammo2.Amount >= 0) )
{
MagAmmo sb = MagAmmo(FindInventory("CandyGunBullets"));
int takeamt = min(sb.Amount,sb.ClipSize);
invoker.clipcount = takeamt;
sb.Amount -= takeamt;
if ( sv_infiniteammo || FindInventory('PowerInfiniteAmmo',true) )
invoker.clipcount = invoker.default.clipcount;
else if ( invoker.Ammo1.Amount <= 0 )
{
MagAmmo sb = MagAmmo(FindInventory("CandyGunBullets"));
int takeamt = min(sb.Amount,sb.ClipSize);
invoker.clipcount = takeamt;
sb.Amount -= takeamt;
}
else
{
invoker.Ammo1.Amount = max(0,invoker.Ammo1.Amount-1);
invoker.clipcount = invoker.default.clipcount;
}
}
else
if ( invoker.clipcount > 0 )
{
invoker.Ammo1.Amount = max(0,invoker.Ammo1.Amount-1);
invoker.clipcount = invoker.default.clipcount;
invoker.PlayUpSound(self);
return ResolveState("Select");
}
let nw = player.mo.PickPrevWeapon();
if ( nw != invoker ) player.PendingWeapon = nw;
if ( invoker.Amount <= 0 )
{
RemoveInventory(invoker);
invoker.Destroy();
}
else A_FullLower(); // this works
return ResolveState(null);
}
Goto Select;
Stop;
Reload:
XZW2 A 1
{