From 30764fa76475f5f95b3f417e018a9375f3767eac Mon Sep 17 00:00:00 2001 From: Steve Cotton Date: Sun, 3 Jun 2018 23:22:18 +0200 Subject: [PATCH] DiD S12: Alternative campaign finish by letting the hero take the book On the third and subsequent playthroughs of Endless Night, Mal Keshar has learned from the ending of SotA, and can leave the book to be taken by the foolish hero's army. This text doesn't handle the unit that picks up the book being the hero themselves, but the hero seems to be using the normal boss AI of staying near the castle so that probably won't happen anyway. He learns how to lichify level 3 necromancers at the start of the first playthrough, which fits better with the backstory of the book. The png icon for this is copied from SotA. This would close issues #3165 and #3167. [ci skip] --- changelog.md | 4 + .../images/units/icons/icon-lich.png | Bin 0 -> 1355 bytes .../scenarios/12_Endless_Night.cfg | 306 +++++++++++++++++- .../Descent_Into_Darkness/utils/macros.cfg | 141 ++++++++ 4 files changed, 450 insertions(+), 1 deletion(-) create mode 100644 data/campaigns/Descent_Into_Darkness/images/units/icons/icon-lich.png diff --git a/changelog.md b/changelog.md index 270a2e87df4b..a92934fdba4e 100644 --- a/changelog.md +++ b/changelog.md @@ -52,6 +52,10 @@ * Normal healing now happens on turn 1 for all sides except the first. (issue #3562) ## Version 1.14.5+dev + ### Campaigns + * Descent Into Darkness: + * Allow converting L3 necromancers to liches from S12 onwards (issue #3165). + * Added an alternative method of completing the campaign (issue #3167). ### Language and i18n * Updated translations: Chinese (Traditional), French, Italian, Spanish. ### Lua API diff --git a/data/campaigns/Descent_Into_Darkness/images/units/icons/icon-lich.png b/data/campaigns/Descent_Into_Darkness/images/units/icons/icon-lich.png new file mode 100644 index 0000000000000000000000000000000000000000..d66241cda83d9c6bd43c33f876f199c49ec3f7d9 GIT binary patch literal 1355 zcmV-R1+@B!P)X1^@s6FWx?2000FNNkl^=8~vZj9J6?W`TWeM-%B4; zUu3%dt^dY@z5<4kgGd6FW&Jc;!a{VCkCIs3o%UIgnFPFE`Oblqfz<$`j&H;%7IrAOC1Cfct_1 z1j$afiZYHQ8(QAK9(M*YteG8tNTtis61MiluHFfp+S4?Xlp z_1ADdzvZNcoMJp57|H_MINJIq19>-;f=()?JLEBby^;*Tn<*HLFuvp z;NB!awM7YDn7a^ij znl`-7zrQj8z(c_M$=F^LkA%4;xb(AASUTJ#%Jz@#gvw+Ri1-_ zyaLelk^1lZt{3-ibU-bYiG%ka--rlTIFgI9u=&Jhu?)BdeLa3Ly=Yw<^2%~xwVS~! z`SfWo9g!X9Hrb$ya6qp$LMaH{@orQ%2asD`hM)cYJ7{h!fI@Es%P8P-MPb#ZZVaE< z8WbO-sgTQge_LA-f~2QKqouh7zS?rcr6+=sGB`E5A31>%)C)66@ns;&>wt<=K_OSb z92$b}{b>|K0}ZIH&6w&0D)eDtW-MBg2bb54s*c5A85XQmnkJJ7vx;(KOV zBq0%;T4M@9J-X&S*eJN#^@B zJ>=KlwA~3JK_Ws27E`5O8Ni`n866Vnw<-dG@t z3+*a6I%z^*uBb>~`DJ4FesJ*u!wwpdBUcOJT9wKt!nR zTZWjVXw>vBLEXv*v8=Sd3UZlT5E~Iq2edR3)M`$gNk@tkCU3MLSc)=iDBHR%I zf6rpLVjSo>IDndl`EbO#;7E#unMy9wObDZ@&LV%!d$=bBL=4In&xKL15ogf9XAJ`F z^{|Cm#Jt1p!0Kb0aq>h@F#oQR^1dBL#g+)FoI2WuQrT)E-9tM|BSEBp*l5$BVN(Y( z1Lf!)>c+4zlfBv0>%Ks%z8`kv1@Ei~H“I realize now... the world is not ready for our knowledge. I give up on all of them. I am going to live in the old troll city and learn the applications of mountain fire. In some future time, less conservative attitudes will dominate, and I can certainly afford to wait. In the meantime, we are doing what we can to hasten that day.”" + {STORYTXT_BACKGROUND book.jpg} + [/part] + [part] + # po: More text from the epilogue of Secrets of the Ancients + story= _ "“As for me, I have placed some spells on my journal to help keep it from harm, and I will make it conspicuous on this battlefield. I hope that it will eventually make its way into the hands of someone in Tath who is willing to learn.”" + {STORYTXT_BACKGROUND book.jpg} + [/part] + [/then] + [/if] + [if] + {VARIABLE_CONDITIONAL timesForever greater_than_equal_to 2} + [then] + [part] + # po: This text comes from the epilogue of Secrets of the Ancients, edited to avoid revealing the name of the campaign or the names of the protagonists + story = _"“I realize now... the world is not ready for our knowledge. I give up on all of them. I am going to live in the old troll city and learn the applications of mountain fire. In some future time, less conservative attitudes will dominate, and I can certainly afford to wait. In the meantime, we are doing what we can to hasten that day.”" + {STORYTXT_BACKGROUND book.jpg} + [/part] + [part] + # po: More text from the epilogue of Secrets of the Ancients + story= _ "“As for me, I have placed some spells on my journal to help keep it from harm, and I will make it conspicuous on this battlefield. I hope that it will eventually make its way into the hands of someone in Tath who is willing to learn.”" + {STORYTXT_BACKGROUND book.jpg} + [/part] + [part] + story= _ "That final entry in the book gnaws at Mal Keshar. While he was being used by Darken Volk as a pawn, both of them were being using as pawns by the author of the book itself." + {STORYTXT_BACKGROUND end.jpg} + [/part] + [part] + story= _ "The book’s author had left it for a foolish hero to pick up, and the spells protecting it had been strong enough to resist the mages of Tath. Mal Keshar had already made several copies of the book and had no further need of the original; if he allowed another foolish hero to take it, would another student eventually follow in his footsteps? Could the author’s plan work? Might liches eventually be accepted in society, if he simply waited?" + {STORYTXT_BACKGROUND end.jpg} + [/part] + [/then] + [/if] [/story] {DID_TRACK {JOURNEY_12_NEW}} @@ -99,6 +151,15 @@ [/show_if] [/objective] + [objective] + {ALTERNATIVE_OBJECTIVE_CAPTION} + condition=win + description= _ "Allow an enemy unit to take the book" + [show_if] + {VARIABLE_CONDITIONAL timesForever greater_than_equal_to 3} + [/show_if] + [/objective] + [objective] {ALTERNATIVE_OBJECTIVE_CAPTION} condition=win @@ -116,6 +177,11 @@ description="" + _ "Endless Night $timesForever" + "" [/note] + [note] + # po: more text copied from Secrets of the Ancients + description= _ "To turn a necromancer into a lich, right-click on it while it is in a castle." + [/note] + {HAS_NO_TURN_LIMIT} # No {IS_LAST_SCENARIO}, because the player can win and keep on playing @@ -123,6 +189,46 @@ {MODIFY_UNIT (id=Mal Keshar) profile (portraits/malin_lich-ancient.png)} + # There is now a menu option to turn necromancers into liches. + [set_menu_item] + id=lichify + description= _ "Make Into a Lich" + image=units/icons/icon-lich.png + [show_if] + [have_unit] + x=$x1 + y=$y1 + side=1 + type=Necromancer + [/have_unit] + [/show_if] + [command] + [if] + [have_location] + x=$x1 + y=$y1 + terrain=C*^*,K*^*,*^K*,*^C* # castles and keeps + [/have_location] + [then] + [fire_event] + name=lichify # See DiD's macros.cfg, or SotA’s sota-utils.cfg + [primary_unit] + x=$x1 + y=$y1 + [/primary_unit] + [/fire_event] + [/then] + [else] + [message] + speaker=narrator + image=misc/makeshift-altar.png + message= _ "You can only do this in a castle." + [/message] + [/else] + [/if] + [/command] + [/set_menu_item] + [if] {VARIABLE_CONDITIONAL timesForever greater_than 1} @@ -132,6 +238,7 @@ [/then] [else] + {VARIABLE previous_previous_randomHero -1} {VARIABLE previous_randomHero -1} [/else] [/if] @@ -458,6 +565,201 @@ {CLEAR_VARIABLE random} [/else] [/switch] + + # Place the book, and add a victory event if the foolish hero's army + # takes it. Should the unit have to make its way back to the enemy + # keep? Probably not, Mal Keshar is going to let it go anyway; maybe + # he should have to kill the first unit that picks it up and let a + # second enemy pick it up, to make it more convincing for the foolish + # hero. + # + # The dialog would be wrong if the hero picked up the book themselves, + # but that's unlikely to happen, the hero is likely to stay on the keep + # to recruit. + [if] + {VARIABLE_CONDITIONAL timesForever greater_than_equal_to 3} + [then] + {PLACE_IMAGE (items/book5.png) 12 17} + + [event] + name=moveto + first_time_only=yes + [filter] + x,y=12,17 + side=2 + [/filter] + + [remove_item] + x,y=$x1,$y1 + image="items/book5.png" + [/remove_item] + + [switch] + variable=randomHero + [case] + value=human + [message] + speaker=unit + message= _ "That’s an evil grimoire!" + [/message] + + [message] + speaker=Foolish Hero + message= _ "Burn it." + [/message] + + [message] + speaker=Mal Keshar + message= _ "(faking pain) Aaargh!" + [/message] + + [message] + role=unit + message= _ "It’s not catching fire, sir." + [/message] + + [message] + speaker=Foolish Hero + message= _ "But it seems to be hurting the lich. Bring it with us, retreat and let the mages destroy this." + [/message] + [/case] + + [case] + value=bandit + [message] + speaker=unit + message= _ "That’s an evil grimoire!" + [/message] + + [message] + speaker=Foolish Hero + message= _ "Burn it." + [/message] + + [message] + speaker=Mal Keshar + message= _ "(faking pain) Aaargh!" + [/message] + + [message] + role=unit + message= _ "It’s paper, but it won’t burn." + [/message] + + [message] + speaker=Foolish Hero + message= _ "But it seems to be hurting the lich. Grab it, retreat and throw it on a bigger fire. Once we’ve burnt it, maybe the lich will be weaker." + [/message] + [/case] + + [case] + value=elf + [message] + speaker=unit + message= _ "That’s an evil grimoire!" + [/message] + + [message] + speaker=Foolish Hero + # po: "faerie fire" as in the elvish sylph's attack + message= _ "Bring it with us, and let’s retreat. Once it’s burned with faerie fire, maybe the lich will be weakened." + [/message] + [/case] + + [case] + value=dwarf + [message] + speaker=unit + message= _ "That’s an evil grimoire, bound in iron." + [/message] + + [message] + speaker=Foolish Hero + message= _ "Destroy it." + [/message] + + [message] + speaker=Mal Keshar + message= _ "(faking pain) Aaargh!" + [/message] + + [message] + speaker=unit + # po: the speaker is a dwarf + message= _ "My hammer can’t dent it and my axe can’t cut the paper." + [/message] + + [message] + speaker=Foolish Hero + # po: the speaker is a dwarf + message= _ "But it seems to be hurting the lich. Bring it with us, retreat and let the forge destroy it." + [/message] + [/case] + + [case] + value=orc + [message] + speaker=unit + # po: the speaker is an orc + message= _ "The skull on that book looks good." + [/message] + + [message] + speaker=Foolish Hero + message= _ "Idiot." + [/message] + + [message] + speaker=Mal Keshar + message= _ "(faking pain) Aaargh!" + [/message] + + [message] + speaker=unit + message= _ "Uuuuuh, I can’t pull the skull off the book, but that lich screams when I try." + [/message] + + [message] + speaker=Mal Keshar + message= _ "Defend me my minions! Get the book! Aaargh!" + [/message] + + [message] + speaker=Foolish Hero + message= _ "Bring it with you and retreat, let’s take our time smashing that book." + [/message] + [/case] + [/switch] + + [story] + title= _ "Epilogue" + [part] + story= _ "The foolish hero was tricked, and left believing both that the book could be destroyed, and that the lich might be weakened by doing so." + {STORYTXT_BACKGROUND end.jpg} + [/part] + [part] + story= _ "Safely outside the cave, the foolish hero tried to destroy the book. None of the attempts left so much as a dent or char, yet each attempt caused another scream to echo from the cave mouth. Finally the cave entrance collapsed, and everything was still." + {STORYTXT_BACKGROUND end.jpg} + [/part] + [part] + story= _ "Years pass. Every summer when the mountain passes become clear, humans, elves and dwarves patrol to repel orcish raiders. Undead no longer trouble the patrols, and memories of the lich fade to become just background in the tale of the brave hero’s victory." + {STORYTXT_BACKGROUND end.jpg} + [/part] + [part] + story= _ "Rumors circulate that fortune smiles on those patrols. That when attacked by orcs at night, it sometimes seems that more blades than just the patrol’s own are fighting the orcs." + {STORYTXT_BACKGROUND end.jpg} + [/part] + [/story] + + [endlevel] + next_scenario=null + carryover_report=no + save=no + linger_mode=no + [/endlevel] + [/event] + [/then] + [/if] [/event] [event] @@ -576,7 +878,7 @@ [message] role=second - message= _ "I guess we'll never know for sure." + message= _ "I guess we’ll never know for sure." [/message] [/case] @@ -623,4 +925,6 @@ {NEW_GOLD_CARRYOVER 40} [/endlevel] [/event] + + {TURN_INTO_A_LICH} [/scenario] diff --git a/data/campaigns/Descent_Into_Darkness/utils/macros.cfg b/data/campaigns/Descent_Into_Darkness/utils/macros.cfg index 9dc234504663..43d338bb5506 100644 --- a/data/campaigns/Descent_Into_Darkness/utils/macros.cfg +++ b/data/campaigns/Descent_Into_Darkness/utils/macros.cfg @@ -105,3 +105,144 @@ {CLEAR_VARIABLE door_to_open} [/event] #enddef + +# This event turns a necromancer into a lich. It can be activated by an event or from +# a right-click menu option. It needs $unit to be set or it won't do anything. +# +# Taken from Secrets of the Ancients, with the character-specific code removed. +#define TURN_INTO_A_LICH + [event] + name=lichify + first_time_only=no + + # This is just to get a more descriptive name for the "unit" variable. + [set_variables] + name=stored_necromancer + mode=replace + to_variable=unit + [/set_variables] + + # In DiD, only Mal Keshar himself can advance to be an Ancient Lich, and his + # transformation is handled in scenario 11. I've left the SotA AMLA calculation + # code in here, partly because it's easier to keep the code the same, and + # partly in case someone enables the fourth level for other liches. + # + # The necromancer may have AMLAd and had its experience reset to 0. Now, as a + # lich, there is a fourth level available for the unit, and all that experience + # should be applied towards the level-up instead of simply being lost. We will + # "unwind" each AMLA and calculate how much it cost, so we can give back those + # experience points. + [set_variable] + name=num_amlas + # This gives us the number of AMLAs that the unit has had: + value=$stored_necromancer.modifications.advancement.length + [/set_variable] + [set_variable] + # The experience that will be used for the new lich will be at least + # the necromancer's current actual experience. + name=experience_gained_after_max_level + value=$stored_necromancer.experience + [/set_variable] + [set_variable] + # Each AMLA took 20% more experience, so we will need to reduce this + # value as we unwind them. The variable starts out storing the amount + # needed for the *next* AMLA, so we will need to reduce it one step as + # the first operation. + name=experience_for_one_amla + value=$stored_necromancer.max_experience + [/set_variable] + + [while] + [variable] + name=num_amlas + greater_than=0 + [/variable] + [do] + [set_variable] + # Each AMLA increased the experience needed by 20%, which + # is the same as multiplying by 1.2. We reverse that here. + name=experience_for_one_amla + divide=1.2 + [/set_variable] + [set_variable] + # Round it off in case it's a float: + name=experience_for_one_amla + round=0 + [/set_variable] + [set_variable] + # Add the experience that was needed for the previous AMLA + # to the amount that will be given to the lich: + name=experience_gained_after_max_level + add=$experience_for_one_amla + [/set_variable] + [set_variable] + name=num_amlas + sub=1 + [/set_variable] + [/do] + [/while] + + # We are going to create a new unit instead of transforming the old one. + # Using the old unit would leave its AMLAs in effect, changing the hitpoints + # and experience needed to level up. + [unit] + side=1 + type=Lich + x=$stored_necromancer.x + y=$stored_necromancer.y + id=$stored_necromancer.id + name=$stored_necromancer.name + facing=$stored_necromancer.facing + moves=$stored_necromancer.moves + overlays=$stored_necromancer.overlays + hitpoints=$stored_necromancer.hitpoints + canrecruit=$stored_necromancer.canrecruit + attacks_left=$stored_necromancer.attacks_left + experience=$experience_gained_after_max_level + + # Copy the original traits into the new unit: + [modifications] + [insert_tag] + name=trait + variable=stored_necromancer.modifications.trait[0] + [/insert_tag] + [insert_tag] + name=trait + variable=stored_necromancer.modifications.trait[1] + [/insert_tag] + [/modifications] + + to_variable=new_lich # Don't create the unit yet. Just store it. + [/unit] + + # Hitpoints are transferred to the new unit so that turning into a lich doesn't + # heal it. However, this could result in the lich having more HP than its + # maximum. If that is the case, we will reset it to the maximum. + [if] + [variable] + name=new_lich.hitpoints + greater_than=$new_lich.max_hitpoints + [/variable] + [then] + [set_variable] + name=new_lich.hitpoints + value=$new_lich.max_hitpoints + [/set_variable] + [/then] + [/if] + + [unstore_unit] + # The unit will automatically AMLA if its experience is sufficient. + # However, in this campaign only Mal Keshar himself can advance to + # be an Ancient Lich (his transformation is handled in scenario 11). + variable=new_lich + text= _ "Lich" # This text goes by quickly, so it must be short. + red,green,blue=220,0,220 # dark-magic purple + animate=yes + [/unstore_unit] + + [clear_variable] + name=stored_necromancer, new_lich, num_amlas, experience_for_one_amla, experience_gained_after_max_level + [/clear_variable] + [/event] +#enddef