Mapper-settable boss healthbar support.

This commit is contained in:
Mari the Deer 2022-09-11 13:58:49 +02:00
commit a4830f6008
8 changed files with 84 additions and 13 deletions

View file

@ -2,19 +2,31 @@
### Tokens
- **Disabling the store:** Give the player `"SWWMStoreDisabler"` item on map load.
- **Disabling revives:** Give the player `"SWWMReviveDisabler"` item on map load.
- **Disabling the store:**<br/>Give the player `"SWWMStoreDisabler"` item on map load.
- **Disabling revives:**<br/>Give the player `"SWWMReviveDisabler"` item on map load.
**Note:** Tokens are flagged as "unclearable", so they have to be removed directly with `TakeInventory`.
**Note:** Tokens are flagged as *"unclearable"*, so they have to be removed directly with `TakeInventory`.
### Mission log
- **Adding a new entry:** `CallACS("SWWMMissionLog","AddLog","YOUR TEXT HERE")`. Prefixed LANGUAGE entries are supported.
- **Setting the date and time:** `CallACS("SWWMMissionLog","SetClock",year,month,day,hour,minute,"timezone")`. Note that month and day start counting from zero, not one *(for programming-related reasons)*.
- **Adding a new entry:**<br/>`CallACS("SWWMMissionLog","AddLog","YOUR TEXT HERE")`<br/>Prefixed LANGUAGE entries are supported.
- **Setting the date and time:**<br/>`CallACS("SWWMMissionLog","SetClock",year,month,day,hour,minute,"timezone")`<br/>Note that month and day start counting from zero, not one *(for programming-related reasons)*.<br/>Please use abbreviations for timezones *(e.g.: EST, CET)*.
### Custom boss healthbars
Using `CallACS("SWWMHandler","AddBoss",tid,"YOUR TAG HERE")` you can assign a group of monsters that will be treated as a boss fight, with a collective healthbar. Note that each call to this function will clear any active boss encounters. Prefixed LANGUAGE entries can be set as a tag, and the mod can automatically look up an alternative with the *"_FUN"* suffix if *"Fun Tags"* are enabled, should there be one defined.
An optional boolean argument can be passed that flags the boss fight as an *"end game"* boss. This serves little purpose other than allowing one specific achievement *("Kill an end-game boss with the Ynykron")* to work properly.
The tag argument is used for the name above the healthbar, so you can give the boss a custom title *(e.g.: "Woobie, Destroyer of Worlds")*. Passing an empty string will use whatever tag the first monster in the list has.
If the assigned boss is a *"BossBrain"* or a subclass of it, it will look for *"BossEye"* actors as well. This is so the healthbar appears only when the eye *"sees"* a player. Do note that if you have multiple boss eyes in the map *(does anyone do that???)*, this may break as it will always use the first one.
### Placing items
**DEMOLITIONIST** does not have standard DoomEdNums assigned to any of its items by default, in order to avoid potential collisions with other custom maps, so you will have to set them yourself. Copy the following to your MAPINFO:
**DEMOLITIONIST** does not have standard DoomEdNums assigned to any of its items by default, in order to avoid potential collisions with other custom maps, so you will have to set them yourself.
Copy the following to your MAPINFO:
```
DoomEdNums

View file

@ -835,6 +835,7 @@ BT_DRAGON = "Death Wyvern, Nether Beast";
BT_HERESIARCH = "Heresiarch, Demonic Sorcerer";
BT_KORAX = "Korax, Trickster Demon";
BT_DEATHKINGS = "Deathkings of the Dark Citadel";
BT_DOOMTEST = "Test Map Boss";
// fun boss tags
BT_BRUISERS_FUN = "Super Bruiser Bros";
BT_CYBIE_FUN = "Shoot It Until It Dies";
@ -854,6 +855,7 @@ BT_DRAGON_FUN = "A Motherfucking Dragon";
BT_HERESIARCH_FUN = "Very Pissed Off Red Dude";
BT_KORAX_FUN = "Korax the Big Stinky Ugly Bastard";
BT_DEATHKINGS_FUN = "A Very Anticlimactic Boss Rehash";
BT_DOOMTEST = "Oatley, Bane of the Quakers";
// eviternity
BT_ARCHANGELUS = "Archangelus, Celestial Agent";
BT_ARCHANGELUS_FUN = "Big Fucking Angel Dude";

View file

@ -724,6 +724,8 @@ BT_DRAGON = "Wyvern Mortal, Bestia del Inframundo";
BT_HERESIARCH = "Heresiarca, Hechicero Demoníaco";
BT_KORAX = "Korax, Demonio Embaucador";
BT_DEATHKINGS = "Reyes de la Muerte de la Ciudadela Oscura";
BT_DOOMTEST = "Jefe de Mapa de Test";
// fun boss tags
BT_CYBIE_FUN = "Dispara Hasta Que Muera";
BT_SPIDER_FUN = "Cerebrito Idiota";
BT_SPIDER2_FUN = "Cerebrito Idiota Bis";
@ -740,6 +742,7 @@ BT_DRAGON_FUN = "Un Puñetero Dragón";
BT_HERESIARCH_FUN = "Tío Rojo Muy Cabreado";
BT_KORAX_FUN = "Korax el Bastardo Feo Asqueroso";
BT_DEATHKINGS_FUN = "Un Refrito de Jefes muy Anticlimático";
BT_DOOMTEST = "Oatley, Azote de los Cuáqueros";
// eviternity
BT_ARCHANGELUS = "Archangelus, Agente Celestial";
BT_ARCHANGELUS_FUN = "Un Putísimo Ángel Enorme";

View file

@ -1,3 +1,3 @@
[default]
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r433 \cu(Sun 11 Sep 12:35:46 CEST 2022)\c-";
SWWM_SHORTVER="\cw1.3pre r433 \cu(2022-09-11 12:35:46)\c-";
SWWM_MODVER="\cyDEMOLITIONIST \cw1.3pre r434 \cu(Sun 11 Sep 13:58:49 CEST 2022)\c-";
SWWM_SHORTVER="\cw1.3pre r434 \cu(2022-09-11 13:58:49)\c-";

View file

@ -479,6 +479,7 @@ Class SWWMLevelCompatibility : LevelPostProcessor
break;
// Kinsie's Test Map
case 'E43C1797DFD9443D1B4C035327743588':
SetThingID(323,6666); // so this boss brain can have a healthbar
case '81033F4F11F652E9CA875CED06C7AF8C':
case '0D1CAD582F63A179BF8A5E47C12D10C6':
// add collectibles

View file

@ -122,6 +122,52 @@ extend Class SWWMHandler
MAP_EVMAP30 // eviternity
};
static play void AddBoss( int tid, String tag, bool endgame = false )
{
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( !hnd ) return;
hnd.bossactors.Clear();
hnd.initialized = false;
let ai = level.CreateActorIterator(tid);
Actor a;
while ( a = ai.Next() )
{
hnd.bossactors.Push(a);
a.GiveInventory('BossMarker',1);
if ( endgame ) a.GiveInventory('EndgameBossMarker',1);
// boss brain type actors need to set an eye so we can detect when they "aggro"
if ( a is 'BossBrain' )
{
hnd.bossbrainactor = a;
// look for boss eyes
let eye = Actor(ThinkerIterator.Create("BossEye").Next());
hnd.bossviewactor = eye;
}
}
if ( hnd.bossactors.Size() == 0 ) return;
hnd.bosstag = (tag!="")?tag:hnd.bossactors[0].GetTag();
}
static play void AddBossActor( Actor a, String tag, bool endgame = false )
{
if ( !a ) return;
let hnd = SWWMHandler(EventHandler.Find("SWWMHandler"));
if ( !hnd ) return;
hnd.bossactors.Clear();
hnd.initialized = false;
hnd.bossactors.Push(a);
a.GiveInventory('BossMarker',1);
hnd.bosstag = (tag!="")?tag:a.GetTag();
// boss brain type actors need to set an eye so we can detect when they "aggro"
if ( a is 'BossBrain' )
{
hnd.bossbrainactor = a;
// look for boss eyes
let eye = Actor(ThinkerIterator.Create("BossEye").Next());
hnd.bossviewactor = eye;
}
}
private clearscope int WhichVanillaBossMap() const
{
String mapsum = level.GetChecksum();
@ -472,7 +518,7 @@ extend Class SWWMHandler
for ( int i=0; i<bossactors.Size(); i++ )
{
if ( !bossactors[i] ) continue;
thealth += max(0,bossactors[i].Health);
thealth += max(0,bossactors[i].SpawnHealth());
}
hmax = thealth;
for ( int i=0; i<30; i++ ) oldhealth[i] = thealth;
@ -518,7 +564,7 @@ extend Class SWWMHandler
if ( !bbar_f ) bbar_f = TexMan.CheckForTexture("graphics/HUD/BossHealthBarBox.png",TexMan.Type_Any);
if ( !bbar_r ) bbar_r = TexMan.CheckForTexture("graphics/HUD/BossHealthBar.png",TexMan.Type_Any);
if ( !bbar_d ) bbar_d = TexMan.CheckForTexture("graphics/HUD/BossHealthBarDecay.png",TexMan.Type_Any);
Vector2 vpos = ((bar.ss.x-300)/2.,bar.ss.y-(bar.margin+35));
Vector2 vpos = ((bar.ss.x-300)/2.,bar.ss.y-(bar.margin+50));
Screen.DrawTexture(bbar_f,false,vpos.x-2,vpos.y-2,DTA_VirtualWidthF,bar.ss.x,DTA_VirtualHeightF,bar.ss.y,DTA_KeepRatio,true,DTA_Alpha,bossalpha);
if ( hmax )
{
@ -533,7 +579,13 @@ extend Class SWWMHandler
string dnum = String.Format("%d",cummdamage);
Screen.DrawText(mSmallFont,Font.CR_RED,vpos.x+300-mSmallFont.StringWidth(dnum),vpos.y-(mSmallFont.GetHeight()+2),dnum,DTA_VirtualWidthF,bar.ss.x,DTA_VirtualHeightF,bar.ss.y,DTA_KeepRatio,true,DTA_Alpha,bossalpha*calph);
}
Screen.DrawText(mSmallFont,Font.CR_WHITE,vpos.x,vpos.y-(mSmallFont.GetHeight()+2),StringTable.Localize(swwm_funtags?(bosstag.."_FUN"):bosstag),DTA_VirtualWidthF,bar.ss.x,DTA_VirtualHeightF,bar.ss.y,DTA_KeepRatio,true,DTA_Alpha,bossalpha);
String bname = bosstag;
if ( (bname.Left(1) == "$") && swwm_funtags )
{
String fun = bname.."_FUN";
if ( !(StringTable.Localize(fun) ~== fun.Mid(1)) ) bname == fun;
}
Screen.DrawText(mSmallFont,Font.CR_WHITE,vpos.x,vpos.y-(mSmallFont.GetHeight()+2),StringTable.Localize(bname),DTA_VirtualWidthF,bar.ss.x,DTA_VirtualHeightF,bar.ss.y,DTA_KeepRatio,true,DTA_Alpha,bossalpha);
}
// can't use this until I actually figure out how to make those walls damageable

View file

@ -235,6 +235,7 @@ extend Class SWWMHandler
{
level.ReplaceTextures("-noflat-","kinstile",0);
S_ChangeMusic("music/CARDISH1.XM");
AddBoss(6666,"$BT_DOOMTEST"); // for testing boss healthbars
}
// doom vacation map01 hackaround for OPEN script not letting us
// change certain line specials in levelpostprocessor because

View file

@ -3011,7 +3011,7 @@ Class SWWMStatusBar : BaseStatusBar
nalph = clamp(tagtime/20.,0.,1.);
yy = ss.y-(margin+50);
// shift up if boss healthbar is present
if ( hnd && (hnd.bossalpha > 0.) ) yy -= int(25*clamp(hnd.bossalpha*2.,0.,1.));
if ( hnd && (hnd.bossalpha > 0.) ) yy -= int(40*clamp(hnd.bossalpha*2.,0.,1.));
int len = mSmallFont.StringWidth(ntagstr);
double xx = (ss.x-len)/2.;
Screen.Dim("Black",.8*nalph,int((xx-6)*hs),int(yy*hs),int((len+12)*hs),int((h+4)*hs));
@ -3022,7 +3022,7 @@ Class SWWMStatusBar : BaseStatusBar
int mend = max(0,PickupQueue.Size()-MAXPICKUP);
yy = ss.y-(margin+50);
// shift up if boss healthbar is present
if ( hnd && (hnd.bossalpha > 0.) ) yy -= int(25*clamp(hnd.bossalpha*2.,0.,1.));
if ( hnd && (hnd.bossalpha > 0.) ) yy -= int(40*clamp(hnd.bossalpha*2.,0.,1.));
// shift up again if nametag is present
if ( nalph > 0. ) yy -= int((mSmallFont.GetHeight()+6)*clamp(nalph*2.,0.,1.));
for ( int i=PickupQueue.Size()-1; i>=mend; i-- )