From a4830f60085546500877d637f97b42fc0c2866a0 Mon Sep 17 00:00:00 2001 From: Marisa the Magician Date: Sun, 11 Sep 2022 13:58:49 +0200 Subject: [PATCH] Mapper-settable boss healthbar support. --- MAPPING.md | 24 ++++++-- language.def_base | 2 + language.es_base | 3 + language.version | 4 +- zscript/compat/swwm_compat.zsc | 1 + zscript/handler/swwm_handler_vanillaboss.zsc | 58 +++++++++++++++++++- zscript/handler/swwm_handler_worldload.zsc | 1 + zscript/hud/swwm_hud.zsc | 4 +- 8 files changed, 84 insertions(+), 13 deletions(-) diff --git a/MAPPING.md b/MAPPING.md index 2408fccea..a874a7542 100644 --- a/MAPPING.md +++ b/MAPPING.md @@ -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:**
Give the player `"SWWMStoreDisabler"` item on map load. +- **Disabling revives:**
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:**
`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)*.
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 diff --git a/language.def_base b/language.def_base index 1b2377b94..cf42ba93f 100644 --- a/language.def_base +++ b/language.def_base @@ -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"; diff --git a/language.es_base b/language.es_base index df15ab9b5..0a5429051 100644 --- a/language.es_base +++ b/language.es_base @@ -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"; diff --git a/language.version b/language.version index a71237e11..76b1f4d9a 100644 --- a/language.version +++ b/language.version @@ -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-"; diff --git a/zscript/compat/swwm_compat.zsc b/zscript/compat/swwm_compat.zsc index f4d7ec37c..22e873c4b 100644 --- a/zscript/compat/swwm_compat.zsc +++ b/zscript/compat/swwm_compat.zsc @@ -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 diff --git a/zscript/handler/swwm_handler_vanillaboss.zsc b/zscript/handler/swwm_handler_vanillaboss.zsc index ec470f54c..35b8a7c7a 100644 --- a/zscript/handler/swwm_handler_vanillaboss.zsc +++ b/zscript/handler/swwm_handler_vanillaboss.zsc @@ -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 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-- )