diff --git a/campgns/lqizgood/map00208.txt b/campgns/lqizgood/map00208.txt index 070c6b00de..6adb2dfcc9 100644 --- a/campgns/lqizgood/map00208.txt +++ b/campgns/lqizgood/map00208.txt @@ -8,6 +8,7 @@ LEVEL_VERSION(1) SET_GENERATE_SPEED(400) SET_PLAYER_COLOR(PLAYER0,WHITE) +SET_PLAYER_COLOR(PLAYER1,RED) SET_PLAYER_COLOR(PLAYER_GOOD,RED) MAX_CREATURES(PLAYER1,15) @@ -105,8 +106,6 @@ DOOR_AVAILABLE(ALL_PLAYERS,MAGIC,1,0) TRAP_AVAILABLE(ALL_PLAYERS,LIGHTNING,1,0) TRAP_AVAILABLE(ALL_PLAYERS,WORD_OF_POWER,1,0) -SET_TIMER(PLAYER0,TIMER0) - CREATE_PARTY(ATTACK) ADD_TO_PARTY(ATTACK,SORCEROR,6,0,ATTACK_DUNGEON_HEART,0) ADD_TO_PARTY(ATTACK,DARK_MISTRESS,7,0,ATTACK_DUNGEON_HEART,0) @@ -114,7 +113,7 @@ CREATE_PARTY(ATTACK) IF(PLAYER0,GAME_TURN > 20) - REM "We have stumbled across a land with no accsessable portals. You also have the torture chamber and prison available, you know what to do! Persuade some people to join you, and torture the rest!" + REM "We have stumbled across a land with no accessable portals. You also have the torture chamber and prison available, you know what to do! Persuade some people to join you, and torture the rest!" DISPLAY_OBJECTIVE(40,ALL_PLAYERS) ENDIF @@ -128,6 +127,15 @@ IF(PLAYER0,TIME_MAGE == 1) DISPLAY_INFORMATION(26,ALL_PLAYERS) ENDIF +IF(PLAYER_GOOD,TOTAL_CREATURES <= 2) + SET_TIMER(PLAYER1,TIMER1) +ENDIF +IF(PLAYER1,TIMER1 > 250) + IF(PLAYER1,BATTLES_LOST < 5) + COMPUTER_DIG_TO_LOCATION(PLAYER1,PLAYER1,PLAYER0) + ENDIF +ENDIF + IF(PLAYER0,ALL_DUNGEONS_DESTROYED == 1) WIN_GAME ENDIF diff --git a/campgns/origplus.cfg b/campgns/origplus.cfg index e3d2ff83a5..5d0ec0c9de 100644 --- a/campgns/origplus.cfg +++ b/campgns/origplus.cfg @@ -66,7 +66,7 @@ NAME_ID = 202 ENSIGN_POS = 808 546 ENSIGN_ZOOM = 808 546 PLAYERS = 1 -SPEECH = good01.wav bad01.wav +SPEECH = good01.mp3 bad01.mp3 LAND_VIEW = rgmap01 viframe01 ENSIGN = @@ -76,7 +76,7 @@ NAME_ID = 203 ENSIGN_POS = 927 524 ENSIGN_ZOOM = 927 524 PLAYERS = 1 -SPEECH = good02.wav bad02.wav +SPEECH = good02.mp3 bad02.mp3 LAND_VIEW = rgmap02 viframe02 ENSIGN = @@ -86,7 +86,7 @@ NAME_ID = 204 ENSIGN_POS = 966 704 ENSIGN_ZOOM = 966 704 PLAYERS = 1 -SPEECH = good03.wav bad03.wav +SPEECH = good03.mp3 bad03.mp3 LAND_VIEW = rgmap03 viframe03 ENSIGN = @@ -96,7 +96,7 @@ NAME_ID = 205 ENSIGN_POS = 842 682 ENSIGN_ZOOM = 838 682 PLAYERS = 1 -SPEECH = good04.wav bad04.wav +SPEECH = good04.mp3 bad04.mp3 LAND_VIEW = rgmap04 viframe04 ENSIGN = @@ -106,7 +106,7 @@ NAME_ID = 206 ENSIGN_POS = 717 617 ENSIGN_ZOOM = 717 617 PLAYERS = 1 -SPEECH = good05.wav bad05.wav +SPEECH = good05.mp3 bad05.mp3 LAND_VIEW = rgmap05 viframe05 ENSIGN = @@ -116,7 +116,7 @@ NAME_ID = 207 ENSIGN_POS = 566 748 ENSIGN_ZOOM = 590 748 PLAYERS = 1 -SPEECH = good06.wav bad06.wav +SPEECH = good06.mp3 bad06.mp3 LAND_VIEW = rgmap06 viframe06 ENSIGN = @@ -126,7 +126,7 @@ NAME_ID = 208 ENSIGN_POS = 445 688 ENSIGN_ZOOM = 469 688 PLAYERS = 1 -SPEECH = good07.wav bad07.wav +SPEECH = good07.mp3 bad07.mp3 LAND_VIEW = rgmap07 viframe07 ENSIGN = @@ -136,7 +136,7 @@ NAME_ID = 209 ENSIGN_POS = 495 577 ENSIGN_ZOOM = 519 577 PLAYERS = 1 -SPEECH = good08.wav bad08.wav +SPEECH = good08.mp3 bad08.mp3 LAND_VIEW = rgmap08 viframe08 ENSIGN = @@ -146,7 +146,7 @@ NAME_ID = 210 ENSIGN_POS = 435 518 ENSIGN_ZOOM = 459 518 PLAYERS = 1 -SPEECH = good09.wav bad09.wav +SPEECH = good09.mp3 bad09.mp3 LAND_VIEW = rgmap09 viframe09 ENSIGN = @@ -156,7 +156,7 @@ NAME_ID = 211 ENSIGN_POS = 379 458 ENSIGN_ZOOM = 403 458 PLAYERS = 1 -SPEECH = good10.wav bad10.wav +SPEECH = good10.mp3 bad10.mp3 LAND_VIEW = rgmap10 viframe10 ENSIGN = @@ -166,7 +166,7 @@ NAME_ID = 212 ENSIGN_POS = 429 379 ENSIGN_ZOOM = 453 379 PLAYERS = 1 -SPEECH = good11.wav bad11.wav +SPEECH = good11.mp3 bad11.mp3 LAND_VIEW = rgmap11 viframe11 ENSIGN = @@ -176,7 +176,7 @@ NAME_ID = 213 ENSIGN_POS = 535 475 ENSIGN_ZOOM = 559 475 PLAYERS = 1 -SPEECH = good12.wav bad12.wav +SPEECH = good12.mp3 bad12.mp3 LAND_VIEW = rgmap12 viframe12 ENSIGN = @@ -186,7 +186,7 @@ NAME_ID = 214 ENSIGN_POS = 627 550 ENSIGN_ZOOM = 651 550 PLAYERS = 1 -SPEECH = good13.wav bad13.wav +SPEECH = good13.mp3 bad13.mp3 LAND_VIEW = rgmap13 viframe13 ENSIGN = @@ -196,7 +196,7 @@ NAME_ID = 215 ENSIGN_POS = 670 483 ENSIGN_ZOOM = 694 483 PLAYERS = 1 -SPEECH = good14.wav bad14.wav +SPEECH = good14.mp3 bad14.mp3 LAND_VIEW = rgmap14 viframe14 ENSIGN = @@ -206,7 +206,7 @@ NAME_ID = 216 ENSIGN_POS = 534 397 ENSIGN_ZOOM = 558 397 PLAYERS = 1 -SPEECH = good15.wav bad15.wav +SPEECH = good15.mp3 bad15.mp3 LAND_VIEW = rgmap15 viframe15 ENSIGN = @@ -216,7 +216,7 @@ NAME_ID = 217 ENSIGN_POS = 662 415 ENSIGN_ZOOM = 686 415 PLAYERS = 1 -SPEECH = good16.wav bad16.wav +SPEECH = good16.mp3 bad16.mp3 LAND_VIEW = rgmap16 viframe16 ENSIGN = @@ -226,7 +226,7 @@ NAME_ID = 218 ENSIGN_POS = 828 445 ENSIGN_ZOOM = 852 445 PLAYERS = 1 -SPEECH = good17.wav bad17.wav +SPEECH = good17.mp3 bad17.mp3 LAND_VIEW = rgmap17 viframe17 ENSIGN = @@ -236,7 +236,7 @@ NAME_ID = 219 ENSIGN_POS = 905 357 ENSIGN_ZOOM = 929 357 PLAYERS = 1 -SPEECH = good18.wav bad18.wav +SPEECH = good18.mp3 bad18.mp3 LAND_VIEW = rgmap18 viframe18 ENSIGN = @@ -246,7 +246,7 @@ NAME_ID = 220 ENSIGN_POS = 632 318 ENSIGN_ZOOM = 656 318 PLAYERS = 1 -SPEECH = good19.wav bad19.wav +SPEECH = good19.mp3 bad19.mp3 LAND_VIEW = rgmap19 viframe19 ENSIGN = @@ -256,7 +256,7 @@ NAME_ID = 221 ENSIGN_POS = 541 242 ENSIGN_ZOOM = 601 242 PLAYERS = 1 -SPEECH = good20.wav bad20.wav +SPEECH = good20.mp3 bad20.mp3 LAND_VIEW = rgmap20 viframe20 ENSIGN = diff --git a/docs/keeperfx_readme.txt b/docs/keeperfx_readme.txt index 15f91430ba..8a7b46e092 100644 --- a/docs/keeperfx_readme.txt +++ b/docs/keeperfx_readme.txt @@ -4,144 +4,132 @@ Dungeon Keeper Fan Expansion KeeperFX is an extensive mod for Dungeon Keeper. It is written by fans and not supported by the original developer. - It contains some of original Dungeon Keeper data, but many files + It contains some of the original Dungeon Keeper data, but many files are also modified or remade. - You can use your original disk, or the GOG/Origins versions of the - game to complete the installation. This fan expansion offers bug - fixes, quality of live improvements and new content, while + You can use your original disk, or the GOG/Steam/Origin versions of + the game to complete the installation. This fan expansion offers + bug fixes, quality of live improvements and new content while retaining the feel of the original game. -Installation of KeeperFX CCP: +Installation of KeeperFX: You need an original version of Dungeon Keeper - a CD (or CD image) - or the installed GOG or Origin versions - to perform a + or the installed GOG, Steam or Origin versions - to perform a complete installation. - To install KeeperFX CCP, you have to unpack the archive to - your desired target location, and then run "launcher.exe". - The Launcher utility will allow you to select source folder - from which original DK files will be taken. To select the - "keeper" folder and start copying files, press "Install" button. - + To install KeeperFX, unpack the archive to your desired target location + and run "keeperfx-launcher-qt.exe". + It will automatically detect a source folder from which original DK files + will be taken. Follow the on screen instructions. + + Users that do not use Windows 10 or newer will have to use "launcher.exe" + instead. This legacy launcher will allow you to install + by selecting a source folder. Click 'Installation' then find + the "keeper" folder with the required files. When using a CD version you must select the "keeper" folder from the CD - content list. Selecting the root folder installation folder on disk, - won't be enough. For the version from GOG.com, the installation folder - will be usable. On the E.A. Origin version you need to select the - 'data' sub-folder + content list. Selecting the root folder installation folder on disk + won't be enough. + GOG: use the installation folder. + Origin: select the 'data' sub-folder. + Steam: find it in steam/steamapps/common/Dungeon Keeper/. - If you wish to change language, click "Settings" in the launcher - and select it from list. Remember to save your changes. You may - also edit "keeperfx.cfg" by hand, using text editor. + Changing the language of both the game and launcher is possible. Press the correct button inside Launcher to start the game. + For information about running the game executable directly, see 'running KeeperFX' section. If something doesn't work, see the 'troubleshooting' section. Available languages: - The following languages are currently functional: + The following languages are fully functional: ENG ITA FRE SPA DUT GER POL SWE JPN RUS CZE KOR CHI The following languages are partially functional: CHT LAT UKR POR Note that some campaigns may not support your language. - In this case, default language will be used inside this - campaign. - -Available screen resolutions: - - To change available screen modes, edit "keeperfx.cfg". - Screen mode can be in a form WIDTHxHEIGHTxBPP which defines - fullscreen mode, or WIDTHxHEIGHTwBPP, which defines windowed - mode. When defining windowed mode, the BPP should be equal to - the colour depth on your desktop. It is not recommended to - mix fullscreen and windowed modes in one config file. - There are two lines which define resolutions: 'FRONTEND_RES=' - should have exactly 3 parameters and is used in the menu, - while 'INGAME_RES=' can have 1-5 parameters, which define - list of resolutions to switch between in the actual game. + In that case the default language will be used. + Running KeeperFX: - To start the game, run "keeperfx.exe". If you want to report - any errors you encounter, you may run "keeperfx_hvlog.exe" - instead. This will run a "heavylog version", which writes a lot - of information into "keeperfx.log". In case of the game hanging - on suddenly disappearing, you may send a last few lines of the - generated LOG to the author with your description of the bug. - - Note that "keeperfx_hvlog.exe" requires a lot more CPU than - standard version, and may be slow even on new computers. - Also, the generated LOG file may be very large, and after - a few hours of play it will have several hundreds megabytes. - This is why you should use standard "keeperfx.exe" if you're - not planning reporting any errors. Zip the log files before - sending them. + To start the game, run the launcher and press 'Play'. Users of the + legacy launcher press 'Start game'. You can also run "keeperfx.exe" + directly. - Both versions will recognize all command line options mentioned - below. + If you want to report any errors you encounter, you may + run "keeperfx_hvlog.exe" instead. + This will run a "heavylog version", which writes a lot of information + into "keeperfx.log". In case of the game hanging + on suddenly disappearing, you may send the last few lines of the + generated LOG to the authors with your description of the bug. -Command line options: + Note that "keeperfx_hvlog.exe" may be slow even on new computers. - KeeperFX accepts many command line options, which you can type - while starting the game, or select from launcher. - All the options are listed and described on Wiki page: - https://github.com/dkfans/keeperfx/wiki/Command-Line-Options + Also, the generated LOG file may be very large. After + a few hours of play it will be several hundred megabytes large. + Use the standard "keeperfx.exe" if you're not experiencing any errors. + Zip the log files before sending them. + + Both versions will recognize all command line options mentioned + below. Troubleshooting: - There's a faq found on Wiki page: + There's an FAQ found on the Wiki page: https://github.com/dkfans/keeperfx/wiki/Troubleshooting If your problem is not listed there, open keeperfx.log with a text editor and read the first and last few lines. Often the error is in - plain english and tells you what to do. + plain English and tells you what to do. - Otherwise look for solutions to your problem at: + Otherwise look for solutions to your problem on: https://keeperklan.com/ - If this fails, ask for help on keeperklan, or the discord: + If this fails, ask for help on keeperklan, or the Discord: https://discord.gg/zKTjfDh +Command line options: + + KeeperFX accepts many command line options, which you can type + while starting the game, or select from the launcher. + All the options are listed and described on this Wiki page: + https://github.com/dkfans/keeperfx/wiki/Command-Line-Options + Reporting a bug: - If you've found a bug in the game, you may report it to KeeperFX developers. + If you've found a bug in the game, you may report it to the KeeperFX developers. But you will have to to do some tests to gather as much information as possible about the problem. First, if the game crashed, try looking into 'keeperfx.log'. If there are error messages in it, it's possible that you haven't properly installed or - configured KeeperFX. In this case, check the 'Troubleshooting' section for + configured KeeperFX. In this case, check the 'Troubleshooting' section for a description of your problem. Note that running the game again will overwrite - the LOG file, so if you want to keep it, you'll have to make a copy. + the LOG file. If you want to keep it, you'll have to make a copy. + + The second step is to try reproducing the error and generate a more detailed log. + Run 'keeperfx_hvlog.exe' and play the level again, doing similar things you did the first time to check if it crashes. If you can't reproduce the error, there is - Second step is to try reproducing the error, and generate more detailed log. - Run 'keeperfx_hvlog.exe' and play the level again, doing similar things you did - first time, to check if it crashes. If you can't reproduce the error, there is - still a chance that the LOG file from first crash is enough to locate the - problem - so post the copy you've made on issue tracker, with your description - of the problem, and information that you couldn't reproduce it. + still a chance that the LOG file from the first crash is enough to locate the + problem. Post the copy you've made on the issue tracker with your description + of the problem and information that you couldn't reproduce it. - If you was able to reproduce the error, then post detailed description of how - to do it on the issue tracker. Remember to include LOG file created by + If you were able to reproduce the error, please post a description of how + to do it on the issue tracker. Remember to include the LOG file created by the 'heavylog' version of KeeperFX. Note that the log file will be huge - you shouldn't attach it directly. Instead, you can compress it, or just paste - a few (ie. 20) lines from its beginning and its end. Remember to include first + a few (ie. 20) lines from its beginning and its end. Remember to include the first and last line of the LOG - these are crucial, and doing it incorrectly would mislead the developers. - If it is possible to reproduce the error by loading specific saved game and + If it is possible to reproduce the error by loading a specific saved game and doing a few simple actions, then attach the saved game to your report. You can - recognize file which contains specific saved game by number in filename, which - is always equal po position of the saved game slot in 'load' menu. + recognize the file which contains a specific saved game by its number in the filename, which is always equal to the position of the saved game slot in the 'load game' menu. + New in-game commands: Most of the controls can be found in the official manual. The rest here: - https://github.com/dkfans/keeperfx/wiki/New-In-Game-Commands - -New and modified level script commands: - - The commands list has been moved to Wiki, to make it easier to maintain: https://github.com/dkfans/keeperfx/wiki/New-Game-Controls-and-Commands Changelog: @@ -152,4 +140,4 @@ Changelog: A summary can be read here: https://github.com/dkfans/keeperfx/wiki/History-of-KeeperFX-releases -Some data files are copyrighted by Bullfrog Productions. +Some data files are copyrighted by Bullfrog Productions. \ No newline at end of file diff --git a/docs/multiplayer_readme.txt b/docs/multiplayer_readme.txt index 6da9a09221..fa10cf0116 100644 --- a/docs/multiplayer_readme.txt +++ b/docs/multiplayer_readme.txt @@ -41,7 +41,4 @@ key difference. Open port 5555 instead and select TCP/IP from the multiplayer menu. TCP/IP is less suitable for multiplayer as a protocol, and there's no known -reason to use this over ENET/UDP as you will have significantly more lag. -However, this protocal has been around for longer and is no longer being -developed or tested on, there's a chance that new bugs on ENET/UDP have -not ended up in this protocol. +reason to use this over ENET/UDP as you will have significantly more lag. \ No newline at end of file diff --git a/lang/levels/classic/text_chi.po b/lang/levels/classic/text_chi.po index 013eaa7edb..610d591712 100644 --- a/lang/levels/classic/text_chi.po +++ b/lang/levels/classic/text_chi.po @@ -437,42 +437,7 @@ msgctxt "In-game message" msgid "An impressive victory Keeper! I'm sure you will enjoy plundering this land in your own time, but your remaining minions must need a rest?!" msgstr "一次令人印象深刻的胜利,守护者!我猜你打算在闲暇的时间里继续享受掠夺这片土地的乐趣,但你的爪牙们却想要休息一下?!" -#. Skybird's Other Side (lv920) -#: guitext:68 -msgctxt "In-game message" -msgid "You're in Skybird Trill again! What dark forces compel you to return to this realm? It seems the gods seek proof that you can achieve victory no matter which side of the realm your quest begins? Prove that your victory versus the Avatar is unavoidable, no matter where your dungeon must be built!" -msgstr "你又一次来到太阳鸟鸣了!是什么黑暗力量迫使你又一次回到这个王国了?似乎黑暗之神希望你能证明自己,无论你的地下城位于这个王国的哪一边,你都可以取得胜利吧?向他证明,无论你的地下城建在哪一边,都无法阻止你成功地打倒圣者!" - -#. Skybird's Other Side (lv920) -#: guitext:69 -msgctxt "In-game message" -msgid "You have destroyed the Avatar's castle but your rival has already taken the Avatar prisoner. Be that as it may, only the Keeper with the blackest heart can destroy this legendary hero, so ransack your rival's dungeon and take the prize. Hmm, getting a sense of deja-vu Master?" -msgstr "你已经摧毁了圣者的城堡,而你的竞争者则囚禁了圣者。不过,只有一个最黑暗邪恶的守护者才能消灭这位传奇英雄,所以洗劫你敌人的地下城,并获得你的奖品。嗯…似曾相识的场面,主人?" - -#. Skybird's Other Side (lv920) -#: guitext:70 -msgctxt "In-game message" -msgid "You have once more proved yourself to be the ruler of Skybird Trill! The latest Avatar lies amongst your defeated foes; you can put him with his predecessors! Your authority in this realm is unchallenged. For now, anyway........ " -msgstr "你再一次证明了自己才是太阳鸟鸣的统治者!新一任的圣者倒在了被你击败的敌人之中;你可以把他和他的先辈们葬在一起了!你在这个王国的权威是毋庸置疑的。不管怎么说,至少现在如此……" - -#. Skybird's Other Side (lv920) -#: guitext:71 -msgctxt "In-game message" -msgid "Prepare yourself for a plague of angry dwarves! You must deal with these irritating minions robustly Keeper. They are the advance Heroes for a forthcoming attack it seems? " -msgstr "准备好迎接一群愤怒的矮人吧!你必须残忍地消灭这些烦人的仆从。他们似乎就是即将到来的英雄中的先锋队?" - -#. Skybird's Other Side (lv920) -#: guitext:72 -msgctxt "In-game message" -msgid "You have defeated the Avatar! However, you are familiar with this realm, and will know it's never safe to assume victory? " -msgstr "你已经击败了圣者!然而,你已经对这个王国很熟悉了,应该知道现在还没有胜利吧?" - -#. Skybird's Other Side (lv920) -#: guitext:73 -msgctxt "In-game message" -msgid "And so the Avatar has returned with a formidable army! Prepare for the final battle Keeper. The fate of this realm must be decided very soon. " -msgstr "圣者又一次回来了,还带领着一支强大的军队!为最后的战斗做好准备,守护者。这个王国的命运很快就会决定了。" - +#: guitext:68 guitext:69 guitext:70 guitext:71 guitext:72 guitext:73 #: guitext:74 guitext:75 guitext:76 guitext:77 guitext:78 guitext:79 #: guitext:80 guitext:81 guitext:82 guitext:83 guitext:84 guitext:85 #: guitext:86 guitext:87 guitext:88 guitext:89 guitext:90 guitext:91 @@ -496,7 +461,7 @@ msgstr "圣者又一次回来了,还带领着一支强大的军队!为最后 #: guitext:186 guitext:187 guitext:188 guitext:189 guitext:190 guitext:191 #: guitext:192 guitext:193 guitext:194 guitext:195 guitext:196 guitext:197 #: guitext:198 guitext:199 guitext:200 -msgid "" +msgid "Moo" msgstr "" #: guitext:202 diff --git a/lang/levels/classic/text_eng.pot b/lang/levels/classic/text_eng.pot index ff888aef04..7f401c49a0 100644 --- a/lang/levels/classic/text_eng.pot +++ b/lang/levels/classic/text_eng.pot @@ -437,42 +437,7 @@ msgctxt "In-game message" msgid "An impressive victory Keeper! I'm sure you will enjoy plundering this land in your own time, but your remaining minions must need a rest?!" msgstr "" -#. Skybird's Other Side (lv920) -#: guitext:68 -msgctxt "In-game message" -msgid "You're in Skybird Trill again! What dark forces compel you to return to this realm? It seems the gods seek proof that you can achieve victory no matter which side of the realm your quest begins? Prove that your victory versus the Avatar is unavoidable, no matter where your dungeon must be built!" -msgstr "" - -#. Skybird's Other Side (lv920) -#: guitext:69 -msgctxt "In-game message" -msgid "You have destroyed the Avatar's castle but your rival has already taken the Avatar prisoner. Be that as it may, only the Keeper with the blackest heart can destroy this legendary hero, so ransack your rival's dungeon and take the prize. Hmm, getting a sense of deja-vu Master?" -msgstr "" - -#. Skybird's Other Side (lv920) -#: guitext:70 -msgctxt "In-game message" -msgid "You have once more proved yourself to be the ruler of Skybird Trill! The latest Avatar lies amongst your defeated foes; you can put him with his predecessors! Your authority in this realm is unchallenged. For now, anyway........ " -msgstr "" - -#. Skybird's Other Side (lv920) -#: guitext:71 -msgctxt "In-game message" -msgid "Prepare yourself for a plague of angry dwarves! You must deal with these irritating minions robustly Keeper. They are the advance Heroes for a forthcoming attack it seems? " -msgstr "" - -#. Skybird's Other Side (lv920) -#: guitext:72 -msgctxt "In-game message" -msgid "You have defeated the Avatar! However, you are familiar with this realm, and will know it's never safe to assume victory? " -msgstr "" - -#. Skybird's Other Side (lv920) -#: guitext:73 -msgctxt "In-game message" -msgid "And so the Avatar has returned with a formidable army! Prepare for the final battle Keeper. The fate of this realm must be decided very soon. " -msgstr "" - +#: guitext:68 guitext:69 guitext:70 guitext:71 guitext:72 guitext:73 #: guitext:74 guitext:75 guitext:76 guitext:77 guitext:78 guitext:79 guitext:80 guitext:81 guitext:82 guitext:83 guitext:84 guitext:85 guitext:86 guitext:87 guitext:88 guitext:89 guitext:90 guitext:91 guitext:92 guitext:93 guitext:94 guitext:95 guitext:96 guitext:97 guitext:98 guitext:99 guitext:100 guitext:101 guitext:102 guitext:103 guitext:104 guitext:105 guitext:106 guitext:107 guitext:108 guitext:109 guitext:110 guitext:111 guitext:112 guitext:113 #: guitext:114 guitext:115 guitext:116 guitext:117 guitext:118 guitext:119 guitext:120 guitext:121 guitext:122 guitext:123 guitext:124 guitext:125 guitext:126 guitext:127 guitext:128 guitext:129 guitext:130 guitext:131 guitext:132 guitext:133 guitext:134 guitext:135 guitext:136 guitext:137 guitext:138 guitext:139 guitext:140 guitext:141 guitext:142 guitext:143 guitext:144 guitext:145 guitext:146 guitext:147 guitext:148 guitext:149 guitext:150 #: guitext:151 guitext:152 guitext:153 guitext:154 guitext:155 guitext:156 guitext:157 guitext:158 guitext:159 guitext:160 guitext:161 guitext:162 guitext:163 guitext:164 guitext:165 guitext:166 guitext:167 guitext:168 guitext:169 guitext:170 guitext:171 guitext:172 guitext:173 guitext:174 guitext:175 guitext:176 guitext:177 guitext:178 guitext:179 guitext:180 guitext:181 guitext:182 guitext:183 guitext:184 guitext:185 guitext:186 guitext:187 diff --git a/lang/levels/classic/text_fre.po b/lang/levels/classic/text_fre.po index 6c0c8f88d4..0b7d8823c3 100644 --- a/lang/levels/classic/text_fre.po +++ b/lang/levels/classic/text_fre.po @@ -443,42 +443,7 @@ msgctxt "In-game message" msgid "An impressive victory Keeper! I'm sure you will enjoy plundering this land in your own time, but your remaining minions must need a rest?!" msgstr "Une victoire impressionnante Gardien ! Je suis sûr que vous apprécierez de piller cette terre à votre rythme, mais vos serviteurs restants doivent avoir besoin de repos !" -#. Skybird's Other Side (lv920) -#: guitext:68 -msgctxt "In-game message" -msgid "You're in Skybird Trill again! What dark forces compel you to return to this realm? It seems the gods seek proof that you can achieve victory no matter which side of the realm your quest begins? Prove that your victory versus the Avatar is unavoidable, no matter where your dungeon must be built!" -msgstr "Vous êtes à nouveau dans Lyons-Perruche ! Quelles forces obscures vous obligent à retourner dans ce royaume ? Il semble que les dieux cherchent la preuve que vous pouvez remporter la victoire, quel que soit le côté du royaume où commence votre quête ? Prouvez que votre victoire contre l'Avatar est inéluctable, peu importe où votre donjon doit être construit !" - -#. Skybird's Other Side (lv920) -#: guitext:69 -msgctxt "In-game message" -msgid "You have destroyed the Avatar's castle but your rival has already taken the Avatar prisoner. Be that as it may, only the Keeper with the blackest heart can destroy this legendary hero, so ransack your rival's dungeon and take the prize. Hmm, getting a sense of deja-vu Master?" -msgstr "Vous avez détruit le château de l'Avatar mais votre rival a déjà fait prisonnier l'Avatar. Quoi qu'il en soit, seul le Gardien au coeur le plus noir peut détruire ce héros légendaire, alors saccagez le donjon de votre rival et prenez le prix. Hmm, un sentiment de déjà-vu Maître ?" - -#. Skybird's Other Side (lv920) -#: guitext:70 -msgctxt "In-game message" -msgid "You have once more proved yourself to be the ruler of Skybird Trill! The latest Avatar lies amongst your defeated foes; you can put him with his predecessors! Your authority in this realm is unchallenged. For now, anyway........ " -msgstr "Vous avez une fois de plus prouvé que vous êtes le maître de Lyons-Perruche ! Le dernier Avatar se trouve parmi vos ennemis vaincus ; vous pouvez le mettre avec ses prédécesseurs ! Votre autorité dans ce domaine est incontestée. Pour l'instant en tout cas... " - -#. Skybird's Other Side (lv920) -#: guitext:71 -msgctxt "In-game message" -msgid "Prepare yourself for a plague of angry dwarves! You must deal with these irritating minions robustly Keeper. They are the advance Heroes for a forthcoming attack it seems? " -msgstr "Préparez-vous à une invasion de nains en colère ! Vous devez faire face à ces sbires irritants avec force Gardien. Ils sont les éclaireurs pour une prochaine attaque, semble-t-il ? " - -#. Skybird's Other Side (lv920) -#: guitext:72 -msgctxt "In-game message" -msgid "You have defeated the Avatar! However, you are familiar with this realm, and will know it's never safe to assume victory? " -msgstr "Vous avez vaincu l'Avatar ! Cependant, vous connaissez bien ce royaume et saurez qu'il n'est jamais sûr de présumer de la victoire ? " - -#. Skybird's Other Side (lv920) -#: guitext:73 -msgctxt "In-game message" -msgid "And so the Avatar has returned with a formidable army! Prepare for the final battle Keeper. The fate of this realm must be decided very soon. " -msgstr "Et donc l'Avatar est de retour avec une armée redoutable ! Préparez-vous pour la bataille finale Gardien. Le sort de ce royaume doit être décidé très bientôt. " - +#: guitext:68 guitext:69 guitext:70 guitext:71 guitext:72 guitext:73 #: guitext:74 guitext:75 guitext:76 guitext:77 guitext:78 guitext:79 guitext:80 guitext:81 guitext:82 guitext:83 guitext:84 guitext:85 guitext:86 guitext:87 guitext:88 guitext:89 guitext:90 guitext:91 guitext:92 guitext:93 guitext:94 guitext:95 guitext:96 guitext:97 guitext:98 guitext:99 guitext:100 guitext:101 guitext:102 guitext:103 guitext:104 guitext:105 guitext:106 guitext:107 guitext:108 guitext:109 guitext:110 guitext:111 guitext:112 guitext:113 #: guitext:114 guitext:115 guitext:116 guitext:117 guitext:118 guitext:119 guitext:120 guitext:121 guitext:122 guitext:123 guitext:124 guitext:125 guitext:126 guitext:127 guitext:128 guitext:129 guitext:130 guitext:131 guitext:132 guitext:133 guitext:134 guitext:135 guitext:136 guitext:137 guitext:138 guitext:139 guitext:140 guitext:141 guitext:142 guitext:143 guitext:144 guitext:145 guitext:146 guitext:147 guitext:148 guitext:149 guitext:150 #: guitext:151 guitext:152 guitext:153 guitext:154 guitext:155 guitext:156 guitext:157 guitext:158 guitext:159 guitext:160 guitext:161 guitext:162 guitext:163 guitext:164 guitext:165 guitext:166 guitext:167 guitext:168 guitext:169 guitext:170 guitext:171 guitext:172 guitext:173 guitext:174 guitext:175 guitext:176 guitext:177 guitext:178 guitext:179 guitext:180 guitext:181 guitext:182 guitext:183 guitext:184 guitext:185 guitext:186 guitext:187 diff --git a/lang/levels/classic/text_ger.po b/lang/levels/classic/text_ger.po index c4d312fc58..9e89aa1d15 100644 --- a/lang/levels/classic/text_ger.po +++ b/lang/levels/classic/text_ger.po @@ -437,42 +437,7 @@ msgctxt "In-game message" msgid "An impressive victory Keeper! I'm sure you will enjoy plundering this land in your own time, but your remaining minions must need a rest?!" msgstr "Ein eindrucksvoller Sieg, Keeper! Ich bin mir sicher, dass Ihr es genießen werdet, dieses Land in Eurer kostbaren Zeit zu plündern, aber Eure verbleibenden Untergebenen müssen sich ausruhen?!" -#. Skybird's Other Side (lv920) -#: guitext:68 -msgctxt "In-game message" -msgid "You're in Skybird Trill again! What dark forces compel you to return to this realm? It seems the gods seek proof that you can achieve victory no matter which side of the realm your quest begins? Prove that your victory versus the Avatar is unavoidable, no matter where your dungeon must be built!" -msgstr "Du bist wieder in Vogelsang! Welche dunklen Mächte treiben Euch dazu, in dieses Reich zurückzukehren? Es scheint, als wollten die Götter den Beweis, dass Ihr siegen könnt, egal auf welcher Seite des Reiches Eure Herausforderung beginnt? Zeige, dass Euer Sieg über den Avatar unvermeidbar ist, ganz gleich, wo Euer Dungeon gebaut wird!" - -#. Skybird's Other Side (lv920) -#: guitext:69 -msgctxt "In-game message" -msgid "You have destroyed the Avatar's castle but your rival has already taken the Avatar prisoner. Be that as it may, only the Keeper with the blackest heart can destroy this legendary hero, so ransack your rival's dungeon and take the prize. Hmm, getting a sense of deja-vu Master?" -msgstr "Ihr habt zwar die Burg des Avatars zerstört, der andere Keeper hat ihn aber gefangen genommen. Sei es, wie es sei, nur der Keeper mit der schwärzesten Seele kann den legendären Helden zur Strecke bringen, also plündert den Dungeon Eures Rivalen und nehmt die Trophäe entgegen. Hmm, bekommt Ihr etwa ein Déjà-vu, Meister?" - -#. Skybird's Other Side (lv920) -#: guitext:70 -msgctxt "In-game message" -msgid "You have once more proved yourself to be the ruler of Skybird Trill! The latest Avatar lies amongst your defeated foes; you can put him with his predecessors! Your authority in this realm is unchallenged. For now, anyway........ " -msgstr "Ihr habt einmal mehr bewiesen, dass Ihr der Herrscher von Vogelsang seid! Der nächste Avatar liegt inmitten Eurer besiegten Feinde; Er kann sich zu seinen Vorgängern gesellen! Eure Vorherrschaft in diesem Reich ist unanfechtbar. Für den Augenblick jedenfalls........ " - -#. Skybird's Other Side (lv920) -#: guitext:71 -msgctxt "In-game message" -msgid "Prepare yourself for a plague of angry dwarves! You must deal with these irritating minions robustly Keeper. They are the advance Heroes for a forthcoming attack it seems? " -msgstr "Macht Euch auf eine Flut von wütenden Zwergen gefasst! Ihr müsst diesen lästigen Lakaien entschieden entgegentreten, Keeper. Sie sind die Vorhut für einen bevorstehenden Angriff, wie es scheint?" - -#. Skybird's Other Side (lv920) -#: guitext:72 -msgctxt "In-game message" -msgid "You have defeated the Avatar! However, you are familiar with this realm, and will know it's never safe to assume victory? " -msgstr "Ihr habt den Avatar geschlagen! Aber Ihr kennt Euch in diesem Reich aus und wisst, dass man sich niemals auf den Sieg verlassen kann? " - -#. Skybird's Other Side (lv920) -#: guitext:73 -msgctxt "In-game message" -msgid "And so the Avatar has returned with a formidable army! Prepare for the final battle Keeper. The fate of this realm must be decided very soon. " -msgstr "Und so ist der Avatar mit einer beachtlichen Armee zurückgekehrt! Die letzte Schlacht steht bevor, Keeper. Das Schicksal dieses Reiches entscheidet sich schon bald." - +#: guitext:68 guitext:69 guitext:70 guitext:71 guitext:72 guitext:73 #: guitext:74 guitext:75 guitext:76 guitext:77 guitext:78 guitext:79 guitext:80 guitext:81 guitext:82 guitext:83 guitext:84 guitext:85 guitext:86 guitext:87 guitext:88 guitext:89 guitext:90 guitext:91 guitext:92 guitext:93 guitext:94 guitext:95 guitext:96 guitext:97 guitext:98 guitext:99 guitext:100 guitext:101 guitext:102 guitext:103 guitext:104 guitext:105 guitext:106 guitext:107 guitext:108 guitext:109 guitext:110 guitext:111 guitext:112 guitext:113 guitext:114 guitext:115 guitext:116 guitext:117 guitext:118 #: guitext:119 guitext:120 guitext:121 guitext:122 guitext:123 guitext:124 guitext:125 guitext:126 guitext:127 guitext:128 guitext:129 guitext:130 guitext:131 guitext:132 guitext:133 guitext:134 guitext:135 guitext:136 guitext:137 guitext:138 guitext:139 guitext:140 guitext:141 guitext:142 guitext:143 guitext:144 guitext:145 guitext:146 guitext:147 guitext:148 guitext:149 guitext:150 guitext:151 guitext:152 guitext:153 guitext:154 guitext:155 guitext:156 guitext:157 guitext:158 guitext:159 guitext:160 guitext:161 #: guitext:162 guitext:163 guitext:164 guitext:165 guitext:166 guitext:167 guitext:168 guitext:169 guitext:170 guitext:171 guitext:172 guitext:173 guitext:174 guitext:175 guitext:176 guitext:177 guitext:178 guitext:179 guitext:180 guitext:181 guitext:182 guitext:183 guitext:184 guitext:185 guitext:186 guitext:187 guitext:188 guitext:189 guitext:190 guitext:191 guitext:192 guitext:193 guitext:194 guitext:195 guitext:196 guitext:197 guitext:198 guitext:199 guitext:200 diff --git a/lang/levels/classic/text_por.po b/lang/levels/classic/text_por.po index 8aa56dc407..0dddb9c303 100644 --- a/lang/levels/classic/text_por.po +++ b/lang/levels/classic/text_por.po @@ -437,42 +437,7 @@ msgctxt "In-game message" msgid "An impressive victory Keeper! I'm sure you will enjoy plundering this land in your own time, but your remaining minions must need a rest?!" msgstr "Uma vitória impressionante, Guardião! Tenho certeza de que você gostará de saquear esta terra em seu próprio tempo, mas seus lacaios restantes devem precisar de um descanso?!" -#. Skybird's Other Side (lv920) -#: guitext:68 -msgctxt "In-game message" -msgid "You're in Skybird Trill again! What dark forces compel you to return to this realm? It seems the gods seek proof that you can achieve victory no matter which side of the realm your quest begins? Prove that your victory versus the Avatar is unavoidable, no matter where your dungeon must be built!" -msgstr "Você está em Canto do Pássaro-do-céu novamente! Que forças sombrias o impelem a retornar a este reino? Parece que os deuses buscam a prova de que você pode alcançar a vitória não importa de que lado do reino sua jornada comece? Prove que sua vitória contra o Avatar é inevitável, não importa onde sua masmorra deva ser construída!" - -#. Skybird's Other Side (lv920) -#: guitext:69 -msgctxt "In-game message" -msgid "You have destroyed the Avatar's castle but your rival has already taken the Avatar prisoner. Be that as it may, only the Keeper with the blackest heart can destroy this legendary hero, so ransack your rival's dungeon and take the prize. Hmm, getting a sense of deja-vu Master?" -msgstr "Você destruiu o castelo do Avatar, mas seu rival já fez o Avatar prisioneiro. Seja como for, apenas o Guardião com o coração mais negro pode destruir este herói lendário, então saqueie a masmorra de seu rival e pegue o prêmio. Hmm, sentindo um deja-vu, Mestre?" - -#. Skybird's Other Side (lv920) -#: guitext:70 -msgctxt "In-game message" -msgid "You have once more proved yourself to be the ruler of Skybird Trill! The latest Avatar lies amongst your defeated foes; you can put him with his predecessors! Your authority in this realm is unchallenged. For now, anyway........ " -msgstr "Você provou mais uma vez ser o governante de Canto do Pássaro-do-céu! O último Avatar jaz entre seus inimigos derrotados; você pode colocá-lo com seus predecessores! Sua autoridade neste reino é incontestável. Por enquanto, de qualquer maneira........" - -#. Skybird's Other Side (lv920) -#: guitext:71 -msgctxt "In-game message" -msgid "Prepare yourself for a plague of angry dwarves! You must deal with these irritating minions robustly Keeper. They are the advance Heroes for a forthcoming attack it seems? " -msgstr "Prepare-se para uma praga de anões furiosos! Você deve lidar com esses lacaios irritantes de forma robusta, Guardião. Eles são os Heróis avançados para um ataque iminente, ao que parece?" - -#. Skybird's Other Side (lv920) -#: guitext:72 -msgctxt "In-game message" -msgid "You have defeated the Avatar! However, you are familiar with this realm, and will know it's never safe to assume victory? " -msgstr "Você derrotou o Avatar! No entanto, você está familiarizado com este reino e sabe que nunca é seguro assumir a vitória?" - -#. Skybird's Other Side (lv920) -#: guitext:73 -msgctxt "In-game message" -msgid "And so the Avatar has returned with a formidable army! Prepare for the final battle Keeper. The fate of this realm must be decided very soon. " -msgstr "E assim o Avatar retornou com um exército formidável! Prepare-se para a batalha final, Guardião. O destino deste reino deve ser decidido muito em breve." - +#: guitext:68 guitext:69 guitext:70 guitext:71 guitext:72 guitext:73 #: guitext:74 guitext:75 guitext:76 guitext:77 guitext:78 guitext:79 guitext:80 guitext:81 guitext:82 guitext:83 guitext:84 guitext:85 guitext:86 guitext:87 guitext:88 guitext:89 guitext:90 guitext:91 guitext:92 guitext:93 guitext:94 guitext:95 guitext:96 guitext:97 guitext:98 guitext:99 guitext:100 guitext:101 guitext:102 guitext:103 guitext:104 guitext:105 guitext:106 guitext:107 guitext:108 guitext:109 guitext:110 guitext:111 guitext:112 guitext:113 #: guitext:114 guitext:115 guitext:116 guitext:117 guitext:118 guitext:119 guitext:120 guitext:121 guitext:122 guitext:123 guitext:124 guitext:125 guitext:126 guitext:127 guitext:128 guitext:129 guitext:130 guitext:131 guitext:132 guitext:133 guitext:134 guitext:135 guitext:136 guitext:137 guitext:138 guitext:139 guitext:140 guitext:141 guitext:142 guitext:143 guitext:144 guitext:145 guitext:146 guitext:147 guitext:148 guitext:149 guitext:150 #: guitext:151 guitext:152 guitext:153 guitext:154 guitext:155 guitext:156 guitext:157 guitext:158 guitext:159 guitext:160 guitext:161 guitext:162 guitext:163 guitext:164 guitext:165 guitext:166 guitext:167 guitext:168 guitext:169 guitext:170 guitext:171 guitext:172 guitext:173 guitext:174 guitext:175 guitext:176 guitext:177 guitext:178 guitext:179 guitext:180 guitext:181 guitext:182 guitext:183 guitext:184 guitext:185 guitext:186 guitext:187 diff --git a/lang/levels/classic/text_spa.po b/lang/levels/classic/text_spa.po index 8b2e124ea5..fd8db11ede 100644 --- a/lang/levels/classic/text_spa.po +++ b/lang/levels/classic/text_spa.po @@ -436,44 +436,7 @@ msgctxt "In-game message" msgid "An impressive victory Keeper! I'm sure you will enjoy plundering this land in your own time, but your remaining minions must need a rest?!" msgstr "¡Una impresionante victoria, Guardián! Estoy seguro de que disfrutarás saqueando esta tierra en tus ratos libres, ¿pero tus servidores restantes deberían poder descansar?" -#. Skybird's Other Side (lv920) -#: guitext:68 -msgctxt "In-game message" -msgid "You're in Skybird Trill again! What dark forces compel you to return to this realm? It seems the gods seek proof that you can achieve victory no matter which side of the realm your quest begins? Prove that your victory versus the Avatar is unavoidable, no matter where your dungeon must be built!" -msgstr "" -"¡Estás en Skybird Trill, otra vez! ¿Qué fuerzas oscuras te obligan a regresar a este reino? ¿Parece que los dioses buscan pruebas, de que puedas lograr una victoria, sin importar de donde este tu reino al comienzo de esta búsqueda? ¡Demuestra que tu victoria contra el Avatar es inevitable, sin importar dónde debas construir tu " -"mazmorra!" - -#. Skybird's Other Side (lv920) -#: guitext:69 -msgctxt "In-game message" -msgid "You have destroyed the Avatar's castle but your rival has already taken the Avatar prisoner. Be that as it may, only the Keeper with the blackest heart can destroy this legendary hero, so ransack your rival's dungeon and take the prize. Hmm, getting a sense of deja-vu Master?" -msgstr "Has destruido el castillo del Avatar, pero tu rival tiene prisionero al Avatar. Sea como sea, solo el Guardián con el corazón más negro puede destruir a este Héroe Legendario, así que saquea la mazmorra de tu rival y toma el premio… Hmm, ¿tienes una sensación de déjà vu, Maestro?" - -#. Skybird's Other Side (lv920) -#: guitext:70 -msgctxt "In-game message" -msgid "You have once more proved yourself to be the ruler of Skybird Trill! The latest Avatar lies amongst your defeated foes; you can put him with his predecessors! Your authority in this realm is unchallenged. For now, anyway........ " -msgstr "¡Has demostrado, una vez más, que eres el gobernante de Skybird Trill! ¡El último Avatar se encuentra entre tus enemigos derrotados, puedes ponerlo con sus predecesores! Tu autoridad en este reino es indiscutible. Por ahora, de todos modos…" - -#. Skybird's Other Side (lv920) -#: guitext:71 -msgctxt "In-game message" -msgid "Prepare yourself for a plague of angry dwarves! You must deal with these irritating minions robustly Keeper. They are the advance Heroes for a forthcoming attack it seems? " -msgstr "¡Prepárate para una plaga de enanos enojados! Debes lidiar con estos molestos servidores con firmeza Guardián. ¿Son los héroes avanzados para un próximo ataque?, parece." - -#. Skybird's Other Side (lv920) -#: guitext:72 -msgctxt "In-game message" -msgid "You have defeated the Avatar! However, you are familiar with this realm, and will know it's never safe to assume victory? " -msgstr "¡Has derrotado al Avatar! Sin embargo, ¿estás familiarizado con este reino? ¿Sabes que nunca es seguro asumir una victoria total?" - -#. Skybird's Other Side (lv920) -#: guitext:73 -msgctxt "In-game message" -msgid "And so the Avatar has returned with a formidable army! Prepare for the final battle Keeper. The fate of this realm must be decided very soon. " -msgstr "¡El Avatar ha regresado con un ejército formidable! Prepárate para la batalla final, Guardián. El destino de este reino debe decidirse muy pronto." - +#: guitext:68 guitext:69 guitext:70 guitext:71 guitext:72 guitext:73 #: guitext:74 guitext:75 guitext:76 guitext:77 guitext:78 guitext:79 guitext:80 guitext:81 guitext:82 guitext:83 guitext:84 guitext:85 guitext:86 guitext:87 guitext:88 guitext:89 guitext:90 guitext:91 guitext:92 guitext:93 guitext:94 guitext:95 guitext:96 guitext:97 guitext:98 guitext:99 guitext:100 guitext:101 guitext:102 guitext:103 #: guitext:104 guitext:105 guitext:106 guitext:107 guitext:108 guitext:109 guitext:110 guitext:111 guitext:112 guitext:113 guitext:114 guitext:115 guitext:116 guitext:117 guitext:118 guitext:119 guitext:120 guitext:121 guitext:122 guitext:123 guitext:124 guitext:125 guitext:126 guitext:127 guitext:128 guitext:129 guitext:130 #: guitext:131 guitext:132 guitext:133 guitext:134 guitext:135 guitext:136 guitext:137 guitext:138 guitext:139 guitext:140 guitext:141 guitext:142 guitext:143 guitext:144 guitext:145 guitext:146 guitext:147 guitext:148 guitext:149 guitext:150 guitext:151 guitext:152 guitext:153 guitext:154 guitext:155 guitext:156 guitext:157 diff --git a/levels/classic/map00920.rules.cfg b/levels/classic/map00920.rules.cfg deleted file mode 100644 index c11085b09f..0000000000 --- a/levels/classic/map00920.rules.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[game] -PreserveClassicBugs = ALWAYS_TUNNEL_TO_RED \ No newline at end of file diff --git a/levels/classic/map00920.txt b/levels/classic/map00920.txt deleted file mode 100644 index e31146e390..0000000000 --- a/levels/classic/map00920.txt +++ /dev/null @@ -1,170 +0,0 @@ -REM Level Skybird's Other Side -REM Skybird's Other Side 2.0.0 -REM Author: Kief, Created on 26 Jul 2007 -REM messages added via pot file by dayokay Dec2020 - -SET_GENERATE_SPEED(1500) - -MAX_CREATURES(PLAYER0,25) -MAX_CREATURES(PLAYER1,30) - -START_MONEY(PLAYER1,20000) -START_MONEY(PLAYER0,2460000) - -COMPUTER_PLAYER(PLAYER1,1) - -ADD_CREATURE_TO_POOL(TROLL,30) -ADD_CREATURE_TO_POOL(SORCEROR,17) -ADD_CREATURE_TO_POOL(BILE_DEMON,20) -ADD_CREATURE_TO_POOL(DARK_MISTRESS,30) -ADD_CREATURE_TO_POOL(DRAGON,21) -ADD_CREATURE_TO_POOL(HELL_HOUND,30) -ADD_CREATURE_TO_POOL(ORC,17) - - -CREATURE_AVAILABLE(ALL_PLAYERS,TROLL,1,1) -CREATURE_AVAILABLE(PLAYER1,SORCEROR,1,1) -CREATURE_AVAILABLE(ALL_PLAYERS,BILE_DEMON,1,1) -CREATURE_AVAILABLE(PLAYER1,DARK_MISTRESS,1,1) -CREATURE_AVAILABLE(PLAYER1,VAMPIRE,1,1) -CREATURE_AVAILABLE(ALL_PLAYERS,DRAGON,1,1) -CREATURE_AVAILABLE(ALL_PLAYERS,HELL_HOUND,1,1) -CREATURE_AVAILABLE(PLAYER0,ORC,1,1) - -ROOM_AVAILABLE(ALL_PLAYERS,TREASURE,1,1) -ROOM_AVAILABLE(ALL_PLAYERS,LAIR,1,1) -ROOM_AVAILABLE(ALL_PLAYERS,GARDEN,1,1) -ROOM_AVAILABLE(ALL_PLAYERS,TRAINING,1,1) -ROOM_AVAILABLE(ALL_PLAYERS,RESEARCH,1,1) -ROOM_AVAILABLE(ALL_PLAYERS,WORKSHOP,1,0) -ROOM_AVAILABLE(ALL_PLAYERS,BARRACKS,1,0) -ROOM_AVAILABLE(ALL_PLAYERS,GUARD_POST,1,0) -ROOM_AVAILABLE(PLAYER1,BRIDGE,1,0) -ROOM_AVAILABLE(ALL_PLAYERS,PRISON,1,0) -ROOM_AVAILABLE(ALL_PLAYERS,TORTURE,1,0) -ROOM_AVAILABLE(ALL_PLAYERS,SCAVENGER,1,0) -ROOM_AVAILABLE(ALL_PLAYERS,TEMPLE,1,0) -ROOM_AVAILABLE(ALL_PLAYERS,GRAVEYARD,1,0) - - -REM Spells - -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_HAND,1,1) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_IMP,1,1) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_SLAP,1,1) -MAGIC_AVAILABLE(PLAYER1,POWER_SIGHT,1,1) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_OBEY,1,0) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_CALL_TO_ARMS,1,0) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_HEAL_CREATURE,1,0) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_SPEED,1,0) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_LIGHTNING,1,0) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_PROTECT,1,0) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_CONCEAL,1,0) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_DISEASE,1,0) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_CAVE_IN,1,0) -MAGIC_AVAILABLE(ALL_PLAYERS,POWER_CHICKEN,1,0) - - -REM doors & traps - -TRAP_AVAILABLE(ALL_PLAYERS,POISON_GAS,1,0) -DOOR_AVAILABLE(ALL_PLAYERS,STEEL,1,0) -TRAP_AVAILABLE(ALL_PLAYERS,BOULDER,1,0) -DOOR_AVAILABLE(ALL_PLAYERS,MAGIC,1,0) -TRAP_AVAILABLE(ALL_PLAYERS,LIGHTNING,1,0) -TRAP_AVAILABLE(ALL_PLAYERS,WORD_OF_POWER,1,0) - - -CREATE_PARTY(RPG) - ADD_TO_PARTY(RPG,WIZARD,10,300,ATTACK_DUNGEON_HEART,0) - ADD_TO_PARTY(RPG,BARBARIAN,10,300,ATTACK_DUNGEON_HEART,0) - ADD_TO_PARTY(RPG,KNIGHT,10,300,ATTACK_DUNGEON_HEART,0) - ADD_TO_PARTY(RPG,WITCH,10,300,ATTACK_DUNGEON_HEART,0) - -CREATE_PARTY(BIG_BOY) - ADD_TO_PARTY(BIG_BOY,AVATAR,10,300,ATTACK_DUNGEON_HEART,0) - ADD_TO_PARTY(BIG_BOY,BARBARIAN,10,300,ATTACK_DUNGEON_HEART,0) - -CREATE_PARTY(BRUTES) - ADD_TO_PARTY(BRUTES,GIANT,10,500,ATTACK_DUNGEON_HEART,0) - ADD_TO_PARTY(BRUTES,GIANT,10,500,ATTACK_DUNGEON_HEART,0) - ADD_TO_PARTY(BRUTES,BARBARIAN,10,500,ATTACK_DUNGEON_HEART,0) - ADD_TO_PARTY(BRUTES,BARBARIAN,10,500,ATTACK_DUNGEON_HEART,0) - -CREATE_PARTY(MAGIC) - ADD_TO_PARTY(MAGIC,WIZARD,10,550,ATTACK_DUNGEON_HEART,0) - ADD_TO_PARTY(MAGIC,KNIGHT,10,550,ATTACK_DUNGEON_HEART,0) - ADD_TO_PARTY(MAGIC,WITCH,10,550,ATTACK_DUNGEON_HEART,0) - ADD_TO_PARTY(MAGIC,SAMURAI,10,550,ATTACK_DUNGEON_HEART,0) - - -CREATE_PARTY(DWARF) - ADD_TO_PARTY(DWARF,DWARFA,9,650,STEAL_GOLD,0) - ADD_TO_PARTY(DWARF,DWARFA,9,650,STEAL_GOLD,0) - ADD_TO_PARTY(DWARF,THIEF,9,3000,STEAL_GOLD,0) - ADD_TO_PARTY(DWARF,THIEF,9,3000,STEAL_GOLD,0) - -DISPLAY_OBJECTIVE(68,PLAYER0) - -IF(PLAYER_GOOD,DUNGEON_DESTROYED == 1) - ROOM_AVAILABLE(PLAYER0,BRIDGE,1,1) - SET_FLAG(PLAYER_GOOD,FLAG0,1) - DISPLAY_OBJECTIVE(69,PLAYER_GOOD) - ADD_CREATURE_TO_LEVEL(PLAYER1,VAMPIRE,PLAYER1,1,10,0) - CREATURE_AVAILABLE(PLAYER0,DARK_MISTRESS,1,1) -ENDIF - -IF(PLAYER_GOOD,AVATAR == 0) - SET_FLAG(PLAYER_GOOD,FLAG1,1) - SET_TIMER(PLAYER_GOOD,TIMER0) - DISPLAY_OBJECTIVE(72,PLAYER0) -ENDIF - -IF(PLAYER_GOOD,FLAG1 == 1) - IF(PLAYER_GOOD,TIMER0 >= 1000) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,MAGIC,-1,1) - ADD_TUNNELLER_PARTY_TO_LEVEL(PLAYER_GOOD,BRUTES,-2,DUNGEON,1,10,100) - ADD_TUNNELLER_PARTY_TO_LEVEL(PLAYER_GOOD,DWARF,-3,DUNGEON,1,10,100) - ADD_TUNNELLER_PARTY_TO_LEVEL(PLAYER_GOOD,DWARF,-6,DUNGEON,1,10,100) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,BRUTES,1,1) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,MAGIC,2,1) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,BRUTES,4,1) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,DWARF,3,1) - ENDIF - IF(PLAYER_GOOD,TIMER0 >= 1133) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,DWARF,3,1) - SET_FLAG(PLAYER_GOOD,FLAG2,1) - DISPLAY_OBJECTIVE(71,PLAYER0) - REM PRINT("HA HA ROBBO (LOW COUNT) YOU ARE DEAD ") - ENDIF - IF(PLAYER_GOOD,TIMER0 >= 1366) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,DWARF,3,1) - SET_FLAG(PLAYER_GOOD,FLAG2,1) - ENDIF - IF(PLAYER_GOOD,TIMER0 >= 1466) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,DWARF,3,1) - SET_FLAG(PLAYER_GOOD,FLAG2,1) - ENDIF - IF(PLAYER_GOOD,TIMER0 >= 1600) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,RPG,3,1) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,BIG_BOY,3,1) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,MAGIC,2,1) - ADD_PARTY_TO_LEVEL(PLAYER_GOOD,BRUTES,4,1) - SET_FLAG(PLAYER_GOOD,FLAG2,1) - DISPLAY_OBJECTIVE(73,PLAYER0) - ENDIF -ENDIF - - -IF(PLAYER_GOOD,FLAG2 == 1) - IF(PLAYER_GOOD,TOTAL_CREATURES == 0) - IF(PLAYER_GOOD,AVATAR == 0) - DISPLAY_OBJECTIVE(70,PLAYER0) - WIN_GAME - ENDIF - ENDIF -ENDIF - -IF(PLAYER0,DUNGEON_DESTROYED == 1) - LOSE_GAME -ENDIF diff --git a/src/bflib_render_trig.c b/src/bflib_render_trig.c index 994c840182..feb18afe50 100644 --- a/src/bflib_render_trig.c +++ b/src/bflib_render_trig.c @@ -2132,6 +2132,10 @@ static inline ulong __ROL4__(ulong value, int count) return value; } +/** + * Flat color fill - renders solid colored triangles with no shading or texturing. + * Used for simple UI elements and solid geometry. + */ void trig_render_md00(struct TrigLocalRend *tlr) { struct PolyPoint *polygon_point; @@ -2177,6 +2181,10 @@ void trig_render_md00(struct TrigLocalRend *tlr) } } +/** + * Gouraud shading - renders smooth color gradients across triangle vertices. + * No texture mapping, just interpolated vertex colors. + */ void trig_render_md01(struct TrigLocalRend *tlr) { struct PolyPoint *polygon_point; @@ -2249,6 +2257,10 @@ void trig_render_md01(struct TrigLocalRend *tlr) } } +/** + * 256x256 texture mapping - renders sprite textures without shading. + * Uses full 8-bit texture coordinates (0-255) for both U and V axes. + */ void trig_render_md02(struct TrigLocalRend *tlr) { struct PolyPoint *polygon_point; @@ -2502,6 +2514,10 @@ void trig_render_md04(struct TrigLocalRend *tlr) } } +/** + * 32x256 terrain texture with shading - renders terrain using 5-bit V (32 rows) + * and 8-bit U (256 columns) texture coordinates, with fade table shading. + */ void trig_render_md05(struct TrigLocalRend *tlr) { struct PolyPoint *polygon_point; @@ -2565,7 +2581,7 @@ void trig_render_md05(struct TrigLocalRend *tlr) if (point_y > vec_window_width) point_y = vec_window_width; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -2588,7 +2604,7 @@ void trig_render_md05(struct TrigLocalRend *tlr) rfactB = (factorB & 0xFFFF0000) | (factorA & 0xFF); rfactA = (factorA & 0xFFFF0000) | (colL & 0xFFFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } o = o_ln; @@ -2611,7 +2627,7 @@ void trig_render_md05(struct TrigLocalRend *tlr) colH = texture_v_lower_byte + rfactB_carry + (colM >> 8); colL = colM; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); *o = f[colS]; } @@ -2673,7 +2689,7 @@ void trig_render_md06(struct TrigLocalRend *tlr) point_x_a = multiplier_x >> 8; colL = (point_x_a >> 8); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); factorB = __ROL4__(polygon_point->S + tlr->shade_step * pXMb, 16); point_x_a = (point_x_a & 0xFFFF00FF) | ((factorB & 0xFF) << 8); @@ -2704,7 +2720,7 @@ void trig_render_md06(struct TrigLocalRend *tlr) factorA = (factorA & 0xFFFF0000) | (polygon_point->U & 0xFFFF); point_x_a = (point_x_a & 0xFFFF00FF) | ((factorB & 0xFF) << 8); factorB = (factorB & 0xFFFF0000) | (pLa & 0xFFFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); point_y = factorB & 0xFFFF; } @@ -2724,7 +2740,7 @@ void trig_render_md06(struct TrigLocalRend *tlr) factorA += texture_v_step_fixed; colH = (tlr->v_step >> 16) + fct_carry + (colM >> 8); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); factorB = (factorB & 0xFFFF0000) | (point_y & 0xFFFF); fct_carry = __CFADDL__(shade_step_fixed, factorB); @@ -2782,7 +2798,7 @@ void trig_render_md07(struct TrigLocalRend *tlr) point_y_a = vec_window_width; point_x_a = (ushort)factorB; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -2801,7 +2817,7 @@ void trig_render_md07(struct TrigLocalRend *tlr) factorA = (factorA & 0xFFFF0000) | (polygon_point->U & 0xFFFF); colL = ((polygon_point->U >> 16) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -2819,7 +2835,7 @@ void trig_render_md07(struct TrigLocalRend *tlr) *o = f[colS]; colH = (colM >> 8) + ((tlr->v_step >> 16) & 0xFF) + factorA_carry; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -2871,7 +2887,7 @@ void trig_render_md08(struct TrigLocalRend *tlr) point_y_a = vec_window_width; point_x_a = (ushort)factorC; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -2890,7 +2906,7 @@ void trig_render_md08(struct TrigLocalRend *tlr) factorA = (factorA & 0xFFFF0000) + (polygon_point->U & 0xFFFF); colL = ((polygon_point->U >> 16) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -2909,7 +2925,7 @@ void trig_render_md08(struct TrigLocalRend *tlr) factorA += texture_v_step_fixed; colH = (colM >> 8) + ((tlr->v_step >> 16) & 0xFF) + factorA_carry; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -2960,7 +2976,7 @@ void trig_render_md09(struct TrigLocalRend *tlr) point_y_a = vec_window_width; point_x_a = (ushort)factorC; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -2979,7 +2995,7 @@ void trig_render_md09(struct TrigLocalRend *tlr) factorA = (factorA & 0xFFFF0000) + (polygon_point->U & 0xFFFF); colL = ((polygon_point->U >> 16) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -3000,16 +3016,27 @@ void trig_render_md09(struct TrigLocalRend *tlr) factorA += texture_v_step_fixed; colH = (colM >> 8) + ((tlr->v_step >> 16) & 0xFF) + factorA_carry; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } +/** + * Translucent sprite rendering - used for creature shadows. + * Samples from 256x256 sprite texture (big_scratch buffer) and blends with + * screen using fade table for shadow transparency effect. + * + * Texture coordinate packing: + * colM = (V_row << 8) | U_column + * - High byte (colH & 0xFF): V coordinate (0-255 rows) - uses 8 bits for sprites + * - Low byte (colL & 0xFF): U coordinate (0-255 columns) + * - Total: 16-bit index into 256x256 = 65536 byte texture + */ void trig_render_md10(struct TrigLocalRend *tlr) { struct PolyPoint *polygon_point; - unsigned char *m; - unsigned char *f; + unsigned char *m; // texture map (256x256 sprite in big_scratch) + unsigned char *f; // fade/transparency table long texture_v_step_fixed; m = vec_map; @@ -3019,6 +3046,11 @@ void trig_render_md10(struct TrigLocalRend *tlr) ERRORLOG("global arrays not set: 0x%p 0x%p 0x%p", m, f, polygon_point); return; } + if (tlr->screen_buffer_ptr == NULL) { + ERRORLOG("screen buffer not set"); + return; + } + // Convert v_step to 16.16 fixed-point for sub-pixel precision texture_v_step_fixed = tlr->v_step << 16; for (; tlr->render_height; tlr->render_height--, polygon_point++) @@ -3042,17 +3074,22 @@ void trig_render_md10(struct TrigLocalRend *tlr) if (point_y_a <= 0) continue; + // Clipping: point starts off-screen left, advance UV to screen edge pXm = (ushort)-(short)point_x_a; + // __ROL4__ rotates 32-bit value left by 16, swapping high/low 16-bit halves + // This extracts the integer part of the fixed-point V coordinate factorA = __ROL4__(polygon_point->V + tlr->v_step * pXm, 16); - colH = factorA; + colH = factorA; // V texture row (integer part) factorB = polygon_point->U + tlr->u_step * pXm; factorA = (factorA & 0xFFFF0000) + (factorB & 0xFFFF); factorC = factorB >> 8; - colL = ((factorC >> 8) & 0xFF); + colL = ((factorC >> 8) & 0xFF); // U texture column (integer part) if (point_y_a > vec_window_width) point_y_a = vec_window_width; point_x_a = (ushort)factorC; + // Pack V row and U column into 16-bit texture index + // 0xFF mask allows full 256 rows (sprite textures), not 0x1F (32 rows for terrain) colM = ((colH & 0xFF) << 8) + (colL & 0xFF); } else @@ -3067,31 +3104,45 @@ void trig_render_md10(struct TrigLocalRend *tlr) if ( (unsigned char)(((point_y_a & 0x8000u) != 0) ^ pY_overflow) | ((ushort)point_y_a == 0) ) continue; o += point_x_a; + // Extract integer part of V coordinate via rotate-left-16 factorA = __ROL4__(polygon_point->V, 16); - colH = factorA; + colH = factorA; // V row factorA = (factorA & 0xFFFF0000) + (polygon_point->U & 0xFFFF); - colL = ((polygon_point->U >> 16) & 0xFF); + colL = ((polygon_point->U >> 16) & 0xFF); // U column + // Pack into texture index: (V_row << 8) | U_column colM = ((colH & 0xFF) << 8) + (colL & 0xFF); } + // Per-pixel scanline loop for (; point_y_a > 0; point_y_a--, o++) { ushort colL, colH; ushort colS; unsigned char factorA_carry; + // Sample texture; if non-zero (inside shadow), apply fade if (m[colM]) { + // Fade table lookup: high byte = shadow intensity, low byte = screen pixel + // Result is blended shadow color colS = (vec_colour << 8) | (*o); *o = f[colS]; } + + // Step U coordinate with carry propagation for fixed-point precision + // __CFADDS__ returns 1 if 16-bit addition overflows (carry flag) factorA_carry = __CFADDS__(tlr->u_step, factorA); factorA = (factorA & 0xFFFF0000) + ((tlr->u_step + factorA) & 0xFFFF); + // Add integer part of u_step plus any carry overflow to U column colL = ((tlr->u_step >> 16) & 0xFF) + factorA_carry + colM; + + // Step V coordinate with carry propagation factorA_carry = __CFADDL__(texture_v_step_fixed, factorA); factorA += texture_v_step_fixed; + // Add integer part of v_step plus any carry overflow to V row colH = (colM >> 8) + ((tlr->v_step >> 16) & 0xFF) + factorA_carry; + // Repack texture index for next pixel colM = ((colH & 0xFF) << 8) + (colL & 0xFF); } } @@ -3144,7 +3195,7 @@ void trig_render_md12(struct TrigLocalRend *tlr) point_y_a = vec_window_width; point_x_a = (ushort)factorB; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -3163,7 +3214,7 @@ void trig_render_md12(struct TrigLocalRend *tlr) factorA = (factorA & 0xFFFF0000) + (polygon_point->U & 0xFFFF); colL = ((polygon_point->U >> 16) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -3181,7 +3232,7 @@ void trig_render_md12(struct TrigLocalRend *tlr) *o = g[colS]; colH = (colM >> 8) + ((tlr->v_step >> 16) & 0xFF) + factorA_carry; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -3232,7 +3283,7 @@ void trig_render_md13(struct TrigLocalRend *tlr) point_y_a = vec_window_width; point_x_a = (ushort)factorC; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -3251,7 +3302,7 @@ void trig_render_md13(struct TrigLocalRend *tlr) factorA = (factorA & 0xFFFF0000) + (polygon_point->U & 0xFFFF); colL = ((polygon_point->U >> 16) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -3269,7 +3320,7 @@ void trig_render_md13(struct TrigLocalRend *tlr) *o = g[colS]; colH = (colM >> 8) + ((tlr->v_step >> 16) & 0xFF) + factorA_carry; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -3418,7 +3469,7 @@ void trig_render_md16(struct TrigLocalRend *tlr) point_y_a = vec_window_width; colL = vec_colour; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -3436,7 +3487,7 @@ void trig_render_md16(struct TrigLocalRend *tlr) factorA = polygon_point->S; colH = (polygon_point->S >> 16); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -3452,7 +3503,7 @@ void trig_render_md16(struct TrigLocalRend *tlr) colH = (colM >> 8) + (tlr->shade_step >> 16) + factorA_carry; colL = colM; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -3580,7 +3631,7 @@ void trig_render_md18(struct TrigLocalRend *tlr) point_y_a = vec_window_width; point_x_a = (ushort)factorC; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -3599,7 +3650,7 @@ void trig_render_md18(struct TrigLocalRend *tlr) factorA = (factorA & 0xFFFF0000) + (polygon_point->U & 0xFFFF); colL = (polygon_point->U >> 16); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -3619,7 +3670,7 @@ void trig_render_md18(struct TrigLocalRend *tlr) *o = g[colS]; colH = (colM >> 8) + ((tlr->v_step >> 16) & 0xFF) + factorA_carry; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -3665,7 +3716,7 @@ void trig_render_md19(struct TrigLocalRend *tlr) if (point_y_a > vec_window_width) point_y_a = vec_window_width; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -3684,7 +3735,7 @@ void trig_render_md19(struct TrigLocalRend *tlr) factorA = (factorA & 0xFFFF0000) + (polygon_point->U & 0xFFFF); colL = ((polygon_point->U >> 16) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -3702,7 +3753,7 @@ void trig_render_md19(struct TrigLocalRend *tlr) *o = g[colS]; colH = (colM >> 8) + (tlr->v_step >> 16) + factorA_carry; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -3756,7 +3807,7 @@ void trig_render_md20(struct TrigLocalRend *tlr) colL = ((point_x_a >> 8) & 0xFF); factorC = __ROL4__(polygon_point->S + tlr->shade_step * pXMb, 16); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -3776,7 +3827,7 @@ void trig_render_md20(struct TrigLocalRend *tlr) colL = ((polygon_point->U >> 16) & 0xFF); factorC = __ROL4__(polygon_point->S, 16); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -3798,7 +3849,7 @@ void trig_render_md20(struct TrigLocalRend *tlr) *o = g[colS]; factorC = (factorC & 0xFFFFFF00) | (((tlr->shade_step >> 16) + factorA_carry + factorC) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -3852,7 +3903,7 @@ void trig_render_md21(struct TrigLocalRend *tlr) factorC = __ROL4__(polygon_point->S + tlr->shade_step * pXMb, 16); point_x_a = (point_x_a & 0xFFFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -3872,7 +3923,7 @@ void trig_render_md21(struct TrigLocalRend *tlr) colL = ((polygon_point->U >> 16) & 0xFF); factorC = __ROL4__(polygon_point->S, 16); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -3894,7 +3945,7 @@ void trig_render_md21(struct TrigLocalRend *tlr) *o = g[colS]; factorC = (factorC & 0xFFFFFF00) | (((tlr->shade_step >> 16) + factorA_carry + factorC) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -3942,7 +3993,7 @@ void trig_render_md22(struct TrigLocalRend *tlr) point_y_a = vec_window_width; point_x_a = factorC & 0xFFFF; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -3961,7 +4012,7 @@ void trig_render_md22(struct TrigLocalRend *tlr) factorA = (factorA & 0xFFFF0000) + (polygon_point->U & 0xFFFF); colL = ((polygon_point->U >> 16) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -3981,7 +4032,7 @@ void trig_render_md22(struct TrigLocalRend *tlr) factorA += texture_v_step_fixed; colH = (colM >> 8) + ((tlr->v_step >> 16) & 0xFF) + factorA_carry; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -4030,7 +4081,7 @@ void trig_render_md23(struct TrigLocalRend *tlr) point_y_a = vec_window_width; point_x_a = (ushort)factorC; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -4049,7 +4100,7 @@ void trig_render_md23(struct TrigLocalRend *tlr) factorA = (factorA & 0xFFFF0000) + (polygon_point->U & 0xFFFF); colL = ((polygon_point->U >> 16) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -4068,7 +4119,7 @@ void trig_render_md23(struct TrigLocalRend *tlr) factorA += texture_v_step_fixed; colH = (colM >> 8) + ((tlr->v_step >> 16) & 0xFF) + factorA_carry; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -4124,7 +4175,7 @@ void trig_render_md24(struct TrigLocalRend *tlr) factorC = __ROL4__(polygon_point->S + tlr->shade_step * pXMb, 16); point_x_a = (ushort)point_x_a; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -4144,7 +4195,7 @@ void trig_render_md24(struct TrigLocalRend *tlr) colL = ((polygon_point->U >> 16) & 0xFF); factorC = __ROL4__(polygon_point->S, 16); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -4169,7 +4220,7 @@ void trig_render_md24(struct TrigLocalRend *tlr) factorC += shade_step_fixed; factorC = (factorC & 0xFFFFFF00) + (((tlr->shade_step >> 16) + factorA_carry + factorC) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } @@ -4225,7 +4276,7 @@ void trig_render_md25(struct TrigLocalRend *tlr) factorC = __ROL4__(polygon_point->S + tlr->shade_step * pXMb, 16); point_x_a = (ushort)point_x_a; - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } else { @@ -4245,7 +4296,7 @@ void trig_render_md25(struct TrigLocalRend *tlr) colL = ((polygon_point->U >> 16) & 0xFF); factorC = __ROL4__(polygon_point->S, 16); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } for (; point_y_a > 0; point_y_a--, o++) @@ -4270,7 +4321,7 @@ void trig_render_md25(struct TrigLocalRend *tlr) factorC += shade_step_fixed; factorC = (factorC & 0xFFFFFF00) | (((tlr->shade_step >> 16) + factorA_carry + factorC) & 0xFF); - colM = ((colH & 0xFF) << 8) + (colL & 0xFF); + colM = ((colH & 0x1F) << 8) + (colL & 0xFF); } } } diff --git a/src/creature_graphics.c b/src/creature_graphics.c index 1a1401d8ee..d7dbe0685e 100644 --- a/src/creature_graphics.c +++ b/src/creature_graphics.c @@ -266,6 +266,15 @@ void get_keepsprite_unscaled_dimensions(long kspr_anim, long angle, long frame, { TbBool val_in_range; struct KeeperSprite* kspr = sprite_by_frame(kspr_anim); + if (kspr == NULL) + { + ERRORLOG("[md10 crash investigation] NULL sprite returned for anim=%ld angle=%ld frame=%ld", kspr_anim, angle, frame); + *orig_w = 0; + *orig_h = 0; + *unsc_w = 0; + *unsc_h = 0; + return; + } if (((angle & ANGLE_MASK) <= DEGREES_202_5) || ((angle & ANGLE_MASK) >= DEGREES_337_5) ) val_in_range = 0; else diff --git a/src/engine_render.c b/src/engine_render.c index c8558cc243..a4aa76b229 100644 --- a/src/engine_render.c +++ b/src/engine_render.c @@ -3906,6 +3906,12 @@ static void create_shadows(struct Thing *thing, struct EngineCoord *ecor, struct short dim_th; short dim_tw; get_keepsprite_unscaled_dimensions(thing->anim_sprite, sprite_angle, thing->current_frame, &dim_ow, &dim_oh, &dim_tw, &dim_th); + if (dim_ow <= 0 || dim_oh <= 0 || dim_ow > 256 || dim_oh > 256) + { + WARNLOG("[md10 crash investigation] Invalid shadow dimensions dim_ow=%d dim_oh=%d for thing %d (anim=%d frame=%d)", + dim_ow, dim_oh, thing->index, thing->anim_sprite, thing->current_frame); + return; + } { int sh_angle_sin = LbSinL(sh_angle); int sh_angle_cos = LbCosL(sh_angle); diff --git a/src/front_landview.c b/src/front_landview.c index 4449fa7e35..61ddf61368 100644 --- a/src/front_landview.c +++ b/src/front_landview.c @@ -380,11 +380,11 @@ const struct TbSprite *get_ensign_sprite_for_level(struct LevelInformation *lvin default: if (lvinfo->lvnum == get_extra_level(ExLv_NewMoon)) { - i = get_disabled_flag_option(lvinfo->ensign, EnsFullMoon); + i = get_disabled_flag_option(lvinfo->ensign, EnsNewMoon); } else { - i = get_disabled_flag_option(lvinfo->ensign, EnsNewMoon); + i = get_disabled_flag_option(lvinfo->ensign, EnsFullMoon); } spr = get_map_ensign(i); break; diff --git a/src/frontmenu_ingame_tabs.c b/src/frontmenu_ingame_tabs.c index 818733b660..d6f0521e03 100644 --- a/src/frontmenu_ingame_tabs.c +++ b/src/frontmenu_ingame_tabs.c @@ -1303,12 +1303,12 @@ void maintain_buildable_info(struct GuiButton* gbtn) !is_trap_built(my_player_number, manufctr->tngmodel))) { gbtn->flags |= LbBtnF_Enabled; - gbtn->tooltip_stridx = 0; + gbtn->tooltip_stridx = GUIStr_Empty; gbtn->sprite_idx = 0; } else { gbtn->flags &= ~LbBtnF_Enabled; - gbtn->tooltip_stridx = 0; + gbtn->tooltip_stridx = GUIStr_Empty; gbtn->sprite_idx = 0; return; } diff --git a/src/player_compevents.c b/src/player_compevents.c index df4c2de61c..633998ca8f 100644 --- a/src/player_compevents.c +++ b/src/player_compevents.c @@ -193,7 +193,7 @@ long computer_event_battle(struct Computer2 *comp, struct ComputerEvent *cevent, } if (computer_able_to_use_power(comp, PwrK_HAND, 1, creatrs_num)) { - if (!is_task_in_progress_using_hand(comp) || ((cevent->secondary_parameter & 0x02) != 0)) + if (!is_task_in_progress(comp, CTT_MoveCreaturesToDefend) || ((cevent->secondary_parameter & 0x02) != 0)) { if (!create_task_move_creatures_to_defend(comp, &pos, creatrs_num, cevent->secondary_parameter)) { SYNCDBG(18,"Cannot move to defend for %s",cevent->name); @@ -333,7 +333,7 @@ long computer_event_battle_test(struct Computer2 *comp, struct ComputerEvent *ce } if (computer_able_to_use_power(comp, PwrK_HAND, 1, creatrs_num)) { - if (!is_task_in_progress_using_hand(comp)) + if (!is_task_in_progress(comp, CTT_MoveCreaturesToDefend)) { if (!create_task_move_creatures_to_defend(comp, &pos, creatrs_num, cevent->secondary_parameter)) { return CTaskRet_Unk4; @@ -572,16 +572,17 @@ long computer_event_attack_door(struct Computer2* comp, struct ComputerEvent* ce return CTaskRet_Unk0; } + int32_t creatrs_def = count_creatures_for_defend_pickup(comp); + if (creatrs_def < cevent->primary_parameter) + { + SYNCDBG(18, "Not enough creatures for event %s", cevent->name); + return CTaskRet_Unk4; + } + if (computer_able_to_use_power(comp, PwrK_HAND, 1, 1)) { if (!is_task_in_progress_using_hand(comp)) { - long creatrs_def = count_creatures_for_defend_pickup(comp); - if (creatrs_def < cevent->primary_parameter) - { - SYNCDBG(18, "Not enough creatures to drop for event %s", cevent->name); - return CTaskRet_Unk4; - } struct Thing* creatng = find_creature_for_defend_pickup(comp); if (thing_is_invalid(creatng)) { diff --git a/src/room_data.c b/src/room_data.c index f002b8e667..66274b91ec 100644 --- a/src/room_data.c +++ b/src/room_data.c @@ -744,6 +744,31 @@ void add_room_to_global_list(struct Room *room) } } +void remove_room_from_global_list(struct Room* room) +{ + // There is only one global list of rooms - the list of entrances + if (room->kind != RoK_ENTRANCE) + return; + + struct Room* pvroom = room_get(room->prev_of_kind); + struct Room* nxroom = room_get(room->next_of_kind); + + if (!room_is_invalid(pvroom)) { + pvroom->next_of_kind = room->next_of_kind; + } + else { + game.entrance_room_id = room->next_of_kind; + } + + if (!room_is_invalid(nxroom)) { + nxroom->prev_of_kind = room->prev_of_kind; + } + + room->next_of_kind = 0; + room->prev_of_kind = 0; + game.entrances_count--; +} + TbBool add_room_to_players_list(struct Room *room, PlayerNumber plyr_idx) { if (room->kind >= game.conf.slab_conf.room_types_count) { @@ -3119,25 +3144,25 @@ void kill_room_slab_and_contents(PlayerNumber plyr_idx, MapSlabCoord slb_x, MapS void free_room_structure(struct Room *room) { PlayerNumber owner = room->owner; - if ( game.neutral_player_num != owner ) - { - struct Dungeon *dungeon = get_dungeon(owner); - if ( room->index == dungeon->room_list_start[room->kind] ) - { - dungeon->room_list_start[room->kind] = room->next_of_owner; - struct Room *next_room = room_get(room->next_of_owner); - next_room->prev_of_owner = 0; - } - else - { - struct Room *next_room = room_get(room->next_of_owner); - next_room->prev_of_owner = room->prev_of_owner; - struct Room *prev_room = room_get(room->prev_of_owner); - prev_room->next_of_owner = room->next_of_owner; - } - --dungeon->room_discrete_count[room->kind]; + struct Dungeon *dungeon = get_dungeon(owner); + + if ( room->index == dungeon->room_list_start[room->kind] ) + { + dungeon->room_list_start[room->kind] = room->next_of_owner; + struct Room *next_room = room_get(room->next_of_owner); + next_room->prev_of_owner = 0; + } + else + { + struct Room *next_room = room_get(room->next_of_owner); + next_room->prev_of_owner = room->prev_of_owner; + struct Room *prev_room = room_get(room->prev_of_owner); + prev_room->next_of_owner = room->next_of_owner; } + --dungeon->room_discrete_count[room->kind]; + + remove_room_from_global_list(room); delete_room_structure(room); } diff --git a/src/room_list.c b/src/room_list.c index 97b3bc80fb..b19e1b6724 100644 --- a/src/room_list.c +++ b/src/room_list.c @@ -52,6 +52,31 @@ void clear_rooms(void) } } +void recalculate_player_roomlist(PlayerNumber plyr_idx,RoomKind rkind) +{ + struct Dungeon* dungeon = get_dungeon(plyr_idx); + + RoomIndex last_idx = 0; + + for (RoomIndex room_idx = 0; room_idx < ROOMS_COUNT; room_idx++) + { + struct Room* room = &game.rooms[room_idx]; + if (!room_is_invalid(room) && (room->owner == plyr_idx) && (room->kind == rkind)) + { + if (last_idx != 0) + { + struct Room* last_room = &game.rooms[last_idx]; + last_room->prev_of_owner = room->index; + } + + room->next_of_owner = last_idx; + dungeon->room_list_start[rkind] = room->index; + last_idx = room->index; + + } + } +} + /** * Counts amount of rooms of specific type owned by specific player. * @param plyr_idx The player number. Only specific player number is accepted. @@ -85,7 +110,8 @@ long count_player_rooms_of_type(PlayerNumber plyr_idx, RoomKind rkind) k++; if (k > ROOMS_COUNT) { - ERRORLOG("Infinite loop detected when sweeping rooms list"); + ERRORLOG("Infinite loop detected when sweeping rooms list %s for player %d",room_code_name(rkind),(int)plyr_idx); + recalculate_player_roomlist(plyr_idx, rkind); break; } } diff --git a/src/thing_creature.c b/src/thing_creature.c index 7be3e80d8b..2fc0306ee4 100644 --- a/src/thing_creature.c +++ b/src/thing_creature.c @@ -3228,6 +3228,7 @@ void prepare_to_controlled_creature_death(struct Thing *thing) set_flag_value(game.operation_flags, GOF_ShowPanel, (game.operation_flags & GOF_ShowGui) != 0); } light_turn_light_on(player->cursor_light_idx); + PaletteSetPlayerPalette(player, engine_palette); } void delete_armour_effects_attached_to_creature(struct Thing *thing) @@ -3330,6 +3331,10 @@ struct Thing *kill_creature(struct Thing *creatng, struct Thing *killertng, Play { create_effect_around_thing(creatng, ball_puff_effects[get_player_color_idx(creatng->owner)]); set_flag(flags, CrDed_NotReallyDying | CrDed_NoEffects); + if (flag_is_set(flags, CrDed_NoEffects) && flag_is_set(creatng->alloc_flags, TAlF_IsControlled)) + { + prepare_to_controlled_creature_death(creatng); + } return cause_creature_death(creatng, flags); } struct Dungeon *dungeon = (!is_neutral_thing(creatng)) ? get_players_num_dungeon(creatng->owner) : INVALID_DUNGEON; diff --git a/version.mk b/version.mk index 79b208ceae..71a32b6e68 100644 --- a/version.mk +++ b/version.mk @@ -1,6 +1,6 @@ VER_MAJOR=1 -VER_MINOR=2 -VER_RELEASE=0 +VER_MINOR=3 +VER_RELEASE=2 VER_BUILD=0 -PACKAGE_SUFFIX= +PACKAGE_SUFFIX= \ No newline at end of file