Ultima Underworld/technical/conversations/141

From Ultima Codex
Jump to navigation Jump to search

Technical Details Warning

While the encyclopedic nature of the codex means that many articles will have information that could spoil some minor aspects of the game for newer players, this article is known to contain technical information about the game, game engine, data files, logic, etc. This information is not generally useful to the typical game players.

Continue reading at your own discretion.

This page contains decompiled conversation code from Ultima Underworld. The original files came from Paul Carr and are currently archived here.

This file has been modified from that source (by Sir Robin) in the following ways:

  • local variables holding pointers to string text have had that string text specified in a comment on that same line. This should make the conversation code easier to read.
  • strings (both dereferenced ones in the code and also the ones added to comments as specified above) have been highlighted for easier reading
  • function definitions have been anchored and function calls have been linked, to make it easier to follow the flow of the code

Start viewing the flow at main

// cnvdasm - ultima underworld conversation script disassembler / decompiler // // loading game strings // // conversation #141 // string block 0x0e8d (3725), name Feznor // // converting to graph // searching functions // replacing expression opcodes // folding expressions // adding control structures // fixing up functions extern int private[31]; void main() { private[1] = 0; func_029d(); func_0012(); } // end func void func_0012() { private[0] = 1; } // end func void func_0020() { int locals[1]; if ( (((npc_goal == 5 || npc_goal == 6) || npc_goal == 9) && npc_gtarg == 1 || npc_attitude == 0) ) { locals[1] = 0; } else { locals[1] = 1; } // end if return locals[1]; } // end func void func_0063() { npc_gtarg = 1; npc_attitude = 1; npc_goal = 6; func_0012(); } // end func void func_007c() { npc_goal = 1; func_0012(); } // end func void func_008b() { npc_gtarg = 1; npc_goal = 5; npc_attitude = 1; func_0012(); } // end func void func_00a4() { npc_attitude = 6; } // end func void func_00b1() { npc_attitude = param1[0]play_hunger; func_0012(); } // end func void func_00c2() { npc_attitude = 2; func_0012(); } // end func void func_00d1() { npc_attitude = 1; func_0012(); } // end func void func_00e0() { func_0012(); } // end func void func_00ea() { param1[1] = game_days; param1[2] = game_mins; } // end func void func_0106() { int locals[4]; locals[2] = game_days - param2[1]; locals[3] = game_mins - param2[2]; if ( locals[3] < 0 ) { locals[3] = locals[3] + 1440; locals[2] = locals[2] - 1; } // end if if ( locals[2] >= param1[1] && locals[3] >= param1[2] ) { locals[1] = 1; } else { locals[1] = 0; } // end if return locals[1]; } // end func void func_018f() { param1[1] = game_days - param3[1]; param1[2] = game_mins - param3[2]; if ( param1[2] < 0 ) { param1[2] = param1[2] + 1440; param1[1] = param1[1] - 1; } // end if param1[1] = param2[1] - param1[1]; param1[2] = param2[2] - param1[2]; if ( param1[2] < 0 ) { param1[2] = param1[2] + 1440; param1[1] = param1[1] - 1; } // end if } // end func void func_0243() { param1[1] = game_days - param2[1]; param1[2] = game_mins - param2[2]; if ( param1[2] < 0 ) { param1[2] = param1[2] + 1440; param1[1] = param1[1] - 1; } // end if } // end func void func_029d() { if ( private[0] == 0 ) { private[2] = 0; } // end if private[3] = 0; func_02b9(); } // end func void func_02b9() { while ( private[2] < 5 ) { if ( private[3] == 0 ) { say( "Welcome, traveller. How can I help thee?" ); private[3] = 1; } else { say( "\mThat is all I can tell thee of that particular matter. What else art thou interested in?" ); } // end if func_02ef(); } // while if ( private[3] == 0 ) { say( "I am sorry but I have no more knowledge to impart to thee. I wish thee good luck in thy quests, whatever they may be and wherever they may take thee." ); } // end if func_05b3(); } // end func void func_02ef() { int locals[22]; locals[1] = 4; // "Tell me of the sights of this level." locals[2] = 6; // "Tell me of the Trolls." locals[3] = 7; // "How did your order come to the Abyss?" locals[4] = 8; // "I thank thee for thy time." locals[5] = 0; // "" locals[22] = babl_menu( 0, &locals[1] ); switch ( locals[22] ) { case 1: if ( private[9] ) { say( "What wouldst thou know?" ); func_03d9(); } else { func_036b(); } // end if break; case 2: func_04b1(); break; case 3: func_053a(); break; case 4: say( "My pleasure." ); func_05b3(); break; } // end switch } // end func void func_036b() { int locals[22]; say( "Ah, yes, this area is wonderfully designed. We created much of it ourselves, with some help from the artisans of Minoc and the Mountainfolk. There are many regions of interest. Although the Abyssal colony has only existed a short time, it is filled with wonders to match any found in Britannia." ); locals[1] = 11; // "Canst thou tell me of these wonders?" locals[2] = 12; // "It does not seem very wondrous to me." locals[3] = 13; // "I have just begun to explore its beauty." locals[4] = 0; // "" locals[22] = babl_menu( 0, &locals[1] ); switch ( locals[22] ) { case 1: func_03c7(); break; case 2: func_05a6(); break; case 3: func_03c7(); break; } // end switch } // end func void func_03c7() { private[9] = 1; say( "In the northeast corner of the level is the Puzzle of the Bullfrog, made by a Mountainfolk craftswoman who had a love of frogs.\n" " To the northwest is the Maze of Silas, a stoneworker and lover of deceptive walls.\n" " Beyond the maze is the door of precious levers, which opens the gateway to the resting place of one of our order.\n" " There is a water-filled area to the west of the Abyss' volcanic core. The waterfall is something to see." ); func_03d9(); } // end func void func_03d9() { int locals[22]; locals[1] = 15; // "Tell me about the Puzzle of the Bullfrog." locals[2] = 16; // "Tell me about the Maze of Silas." locals[3] = 17; // "Tell me about the door of precious levers." locals[4] = 18; // "Tell me about the watery area." locals[5] = 0; // "" locals[22] = babl_menu( 0, &locals[1] ); switch ( locals[22] ) { case 1: func_0446(); break; case 2: func_0460(); break; case 3: func_0494(); break; case 4: func_047a(); break; } // end switch } // end func void func_0446() { if ( private[4] ) { say( "I thought I had already told thee of that.\m" ); } // end if say( "Past the puzzle in the northeast there is an entrance to the tombs below. To reach the entrance, one must traverse an area surrounded by water. It is said that by using the levers and buttons in the area, one may create a safe path to the other side. It has been years since the puzzle was created, though, and its solution is now lost. The only clue I know of is that the wand found there will restore the puzzle to its pristine state." ); private[4] = 1; func_02ef(); } // end func void func_0460() { if ( private[5] ) { say( "I thought I had already told thee of that.\m" ); } // end if say( "The Maze of Silas is now infested with pests and littered with debris and bones, but there are said to be other things in the maze as well -- hidden chambers and items of some value. The locations of these chambers and items are unknown now, however, so what they contain I cannot reveal to thee." ); private[5] = 1; func_02ef(); } // end func void func_047a() { if ( private[7] ) { say( "I thought I had already told thee of that.\m" ); } // end if say( "Near the volcano's shaft is a set of falls leading to two pools.\n" " One pool is very hard to reach, at least from our domain. But 'tis said it is simple to get there from the Lair of the Lizard-Folk. Would that one among us could speak their tongue and learn the easier route.\n" " The second pool is in a secluded spot near a fishing run south of the Abyss' central shaft." ); private[7] = 1; func_02ef(); } // end func void func_0494() { if ( private[6] ) { say( "I thought I had already told thee of that.\m" ); } // end if say( "The puzzle of precious levers is beyond the maze. Although the members of our knighthood will not be specific, it is believed to be in a concealed area.\n" " The puzzle itself was built to guard the stores of the old government of the Abyss. Now, however, not one of us could tell thee what lies beyond the closed door.\m" ); say( "The workings of the levers are not understood, but 'tis said that their secrets can be gleaned through careful examination of the artifacts of our order.\n" " I have not the patience for such research, but perhaps one who does will solve the mystery." ); private[6] = 1; func_02ef(); } // end func void func_04b1() { int locals[22]; if ( private[8] ) { say( "I thought I had already told thee of that.\m" ); } // end if say( "They are indeed a vicious and dangerous race. I would call them indecent, but that was not Cabirus' way, and I strive not to make it mine.\n" " They are, truth be told, honorable in their own way. Only a few of them still cling to any shreds of the Abyss' purpose, though. Some have reverted to their natural, combative state. They are monsters, and powerful ones, at that." ); private[8] = 1; locals[1] = 30; // "How can one pass through their realm safely?" locals[2] = 31; // "I suppose I should be ready to fight." locals[3] = 33; // "I can handle them." locals[4] = 0; // "" locals[22] = babl_menu( 0, &locals[1] ); switch ( locals[22] ) { case 1: func_052a(); break; case 2: say( "Ready, yes, but not eager." ); func_052a(); break; case 3: func_051d(); break; } // end switch } // end func void func_051d() { say( "Part of a knight's goal is to be a good fighter, it is true. But a good fighter does not rejoice in a battle for its own sake.\n" " Thy blade is an ally only when it is used with honor and justice. When it is used for needless bloodshed, it stains thy honor and the honor of thy order.\n" " Do not fight for the sake of killing. Fight for thy life, the life of those thou art sworn to defend, and to eliminate those that threaten our realm. Fighting for the sake of blood is a short road to death." ); func_02ef(); } // end func void func_052a() { say( "Thou needst not fight continually to survive their realm. In the south, where the main meeting hall of the Trolls used to be, there are still Trolls who respect Cabirus' purpose. They can tell thee more of the realm. Beware the Dark Trolls - they are more powerful even than the normal ones.\m" ); say( "Also beware the northern parts of their realm, for they have been invaded by spiders, headlesses, and worse. These monsters will provide enough trouble, so don't attack Trolls unless they attack thee first. Thou wilt have enough trouble staying alive without picking fights." ); func_02ef(); } // end func void func_053a() { int locals[22]; say( "We came here from Jhelom. The fairest town in Britannia, that I can say with certainty. Been to them all I have, and none compare." ); locals[1] = 38; // "Thou dost speak truly." locals[2] = 39; // "It certainly is a fine town." locals[3] = 40; // "Thou dost think so? I disagree." locals[4] = 0; // "" locals[22] = babl_menu( 0, &locals[1] ); switch ( locals[22] ) { case 1: func_0596(); break; case 2: func_0596(); break; case 3: func_05a6(); break; } // end switch } // end func void func_0596() { say( "The colony of the Abyss was an achievement unparalleled in recent times. Eight cultures mixing in one environment, and getting along splendidly. We had some banquets that were spectacular, I tell thee. They rivaled the best of parties that even Jhelom could offer. We would all gather just to the northeast of here in the banquet hall. We would stay up all night -- though of course it is hard to tell down here -- and recount tales of our homelands, our rituals, and our friends.\m" ); say( "Now all we do is fight for food and space. Truly the death of Cabirus was the death of the Colony of the Stygian Abyss. Still, we try, for it is all we can do to honor his legacy and dream." ); func_02ef(); } // end func void func_05a6() { say( "Perhaps the inhabitants of Jhelom were not perfect, but they were certainly more courteous than thee." ); func_00d1(); } // end func void func_05b3() { int locals[22]; locals[1] = 44; // "Farewell." locals[2] = 0; // "" locals[22] = babl_menu( 0, &locals[1] ); if ( locals[22] == 1 ) { func_00e0(); } // end if } // end func void func_05e4() { int locals[44]; setup_to_barter( 0 ); while ( !private[1] ) { locals[1] = 45; // "I make thee this offer." locals[2] = 46; // "I demand thou givest me these items." locals[3] = 47; // "Excuse me, I must think about this deal." locals[4] = 48; // "I do not wish to barter any further." locals[5] = 0; // "" locals[22] = babl_menu( 0, &locals[1] ); switch ( locals[22] ) { case 1: func_0695(); break; case 2: func_06ef(); break; case 3: do_judgement( 0 ); break; case 4: do_decline( 0 ); private[1] = 1; break; } // end switch } // while locals[23] = 49; // "Farewell." locals[24] = 0; // "" locals[44] = babl_menu( 0, &locals[23] ); if ( locals[44] == 1 ) { private[1] = 1; } // end if } // end func void func_0695() { int locals[15]; locals[0] = -1; locals[6] = -1; locals[11] = 50; // "I accept thy offer." locals[12] = 51; // "No, I do not like this deal." locals[13] = 52; // "Dost thou take me for a fool?" locals[14] = 53; // "I am weary of this haggling." locals[15] = 54; // "Surely thou art joking." if ( do_offer( 7, &locals[15], &locals[14], &locals[13], &locals[12], &locals[11], &locals[6], &locals[1] ) ) { private[1] = 1; } // end if } // end func void func_06ef() { int locals[24]; say( "Dost thou intend to rob me?" ); locals[1] = 56; // "Yes, I must." locals[2] = 57; // "No, thou dost misunderstand me." locals[3] = 0; // "" locals[22] = babl_menu( 0, &locals[1] ); switch ( locals[22] ) { case 1: break; case 2: return; break; } // end switch locals[23] = 58; // "If thou dost insist, thou canst have them." locals[24] = 59; // "No! Thou shalt not take them!" if ( do_demand( 2, &locals[24], &locals[23] ) ) { private[1] = 1; } else { func_008b(); } // end if } // end func