Ultima Underworld/technical/conversations/18
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 #18 // string block 0x0e12 (3602), name Lakshi Longtooth // // 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() { int locals[24]; if ( npc_goal == 11 ) { npc_goal = 7; } // end if locals[1] = get_quest( 1, &locals[2] ); locals[2] = 32; if ( private[0] ) { if ( locals[1] > 1 ) { say( "Hello again, knight-who-is-friendly." ); } else { say( "Hello again, human-who-is-not-a-knight." ); } // end if } else { if ( locals[1] > 1 ) { if ( play_drawn ) { say( "Another knight come to slay us all? You no learn your lesson yet?" ); npc_attitude = 1; } else { say( "Knight ventures into our domain without a drawn weapon? You brave." ); } // end if } else { say( "A human enters our domain. This is rare event. Why do you come?" ); } // end if } // end if locals[3] = 6; // "I need some information from thee." locals[4] = 7; // "Canst thou help me in some way?" locals[5] = 8; // "I shall be on my way now." locals[6] = 0; // "" locals[24] = babl_menu( 0, &locals[3] ); switch ( locals[24] ) { case 1: func_034b(); break; case 2: func_034b(); break; case 3: func_00e0(); break; } // end switch } // end func void func_034b() { say( "Maybe. You ask question, I answer." ); func_0358(); } // end func void func_0358() { int locals[31]; while ( 1 ) { locals[2] = 10; // "Canst thou tell me about..." locals[3] = 11; // "Thank you for thy help. Farewell." locals[4] = 0; // "" locals[23] = babl_menu( 0, &locals[2] ); switch ( locals[23] ) { case 1: break; case 2: func_0479(); break; } // end switch locals[1] = babl_ask( 0 ); say( "\1@SS1\0" ); locals[24] = 13; (contains( 2, &locals[1], &locals[24] ) || contains( 2, &locals[1], &locals[25] )); // expr. has value on stack! if ( locals[25] = 14 ) { say( "Rawstag still a young troll, not always do what he told. You give him red gem, maybe he more nice to you." ); } else { locals[26] = 16; if ( contains( 2, &locals[1], &locals[26] ) ) { say( "Sethar lives in cave just north of here, on the west. He is fine troll, a great warrior when young. We all look up to him." ); } else { locals[27] = 18; (contains( 2, &locals[1], &locals[27] ) || contains( 2, &locals[1], &locals[28] )); // expr. has value on stack! if ( locals[28] = 19 ) { say( "The knights talk tough, but they usually keep to themselves. One nasty knight, though. He lives in banquet hall. You watch out for him." ); } else { locals[29] = 21; if ( contains( 2, &locals[1], &locals[29] ) ) { say( "Sethar's pit? Tricky place maybe, but not deadly. Look past bones of old victims, you find way out." ); } else { locals[30] = 23; (contains( 2, &locals[1], &locals[30] ) || contains( 2, &locals[1], &locals[31] )); // expr. has value on stack! if ( locals[31] = 24 ) { say( "Lorne a knight, from start of colony. He used to be friend of us, unlike rest. He often would pray in shrine south of here. He is gone now, but the shrine is still around. Rawstag is a bit possesive about that area though." ); } else { if ( length( 1, &locals[1] ) == 0 ) { say( "Hm? What you want to know about?" ); } else { say( "I don't know about that." ); } // end if } // end if } // end if } // end if } // end if } // end if } // while } // end func void func_0479() { say( "Bye, human." ); func_00e0(); } // end func void func_0486() { int locals[10]; locals[8] = 1; locals[9] = 1; while ( locals[8] <= 6 ) { if ( private[2][0] == 0 ) { locals[0] = locals[8]; locals[9] = locals[9] + 1; } // end if locals[8] = locals[8] + 1; } // while if ( locals[9] == 0 ) { say( "I have no new news for you." ); locals[8] = 1; } // end if if ( locals[8] <= 6 ) { private[2][0] = 0; } else { } // end if locals[8] = random( 1, &locals[9] ); locals[9] = locals[0]; private[2][0] = 1; locals[10] = locals[9]; if ( 1 == locals[10] ) { say( "Me hear one Troll got caught by Wizard, made slave." ); } else { if ( 2 == locals[10] ) { say( "Me hear somebody killing Trolls! Me catch, me eat!" ); } else { if ( 3 == locals[10] ) { say( "Sethar and his friend live near the big pit." ); } else { if ( 4 == locals[10] ) { say( "Sneak snuck on Sethar, but he tossed him in pit." ); } else { if ( 5 == locals[10] ) { say( "One Knight real mean, he live up north." ); } else { if ( 6 == locals[10] ) { say( "Ghouls live below us. They disgusting." ); } // end if } // end if } // end if } // end if } // end if } // end if } // end func void func_0563() { int locals[23]; say( "You food, puny human?" ); locals[1] = 37; // "Yes, come and get it..." locals[2] = 38; // "No, let's not fight." locals[3] = 39; // "Ha! Try it!" locals[4] = 0; // "" locals[22] = babl_menu( 0, &locals[1] ); switch ( locals[22] ) { case 1: func_008b(); break; case 2: break; case 3: func_05cb(); break; } // end switch say( "You confuse me, first want fight and then not want fight." ); locals[23] = 1; func_00b1( &locals[23] ); } // end func void func_05cb() { int locals[1]; if ( play_level + play_drawn > npc_level + 5 ) { func_0063(); } // end if if ( play_level + play_drawn < npc_level - 1 ) { func_008b(); } // end if locals[1] = 1; func_00b1( &locals[1] ); } // end func