I'm a bit late to the party, I suppose, as Ardent's mod was released some time ago yet I only recently played for the first time. This mod is very entertaining, and also quite well-crafted. Great job, Ardent! At some point in the future I hope work resumes on this mod, as if the remainder is anything like the demo I won't be delinquent again in relishing the experience.
I found some of the play a near-revelation, as several novel methods used to facilitate the storyline (e.g. the player-character may be captured and imprisoned, etc) are very engaging. I also thought some of the necessary concessions to mundane Fallout 2 conventions (e.g. the player-character is wearing a Vault 13 suit because he works in a bar called "Vault 13," etc) were quite clever. The storyline manages to offer both appealing humor and grim wasteland realities in equal measures, which can be difficult to create and balance. The mapping, artwork, and writing (grammar, spelling, and so forth) are all first-rate as well, and the "puzzles" (i.e. problems not resolvable by standard Fallout recourse to violence) are both sporting and interesting.
Though Ardent is busy ( ) on other projects ( ), for future reference whenever work on this mod resumes I experienced a few trivial issues and one rather serious problem while playing that I didn't see previously mentioned here.
Trivial:
[spoiler:41f616d840]
--In the Junktown north of Duston, along the eastern edge of the map is a wall covered by grafitti that reads "Metro." A blocker (or three) should be placed here, as characters can walk through the wall.
--Also in the Junktown north of Duston, near the shack where Rob lost his beverages is a Cola Fridge. Note the default proto for this item has "Use" and "Use On" flagged, resulting in a spurious hand-icon appearing when the player looks at the Fridge in-game.
--Perhaps by design, but I'm not sure how Mayor Candlekeeper's store stays in business since his all barter prices are outrageous (compared to other folks who have items to barter around Dunston) even when the player-character obtains a courtesy "discount" as an employee of DiAngelo's.
[/spoiler:41f616d840]
Serious:
I'm sorry to break convention as everyone else has politely been hiding their bug reports in spoiler tags, but I haven't been able to figure out how to successfully include code sections inside spoiler tags on this forum-- so perhaps anyone not interested in scripting should try not to look while scrolling past the remainder of my post...
I had a number of troubles with Dr. Goya, and the matters are fairly complex. Basically the troubles break down into two areas:
a) An FO2 engine problem for which Ardent is not in any way responsible, and
b) Some bugs as well as general weak points in both 0egoya.int and 0einvisc.int.
Regarding (a), though my own skill was sufficient to ameliorate the problem I don't personally know how to effect a decisive fix. The trouble ensues when the game time advancement that occurs whilst the player-character is receiving Goya's therapy triggers an automated Hakunin dream sequence. For me (as seems likely for most plays of the mod), Hakunin's first dream sequence was scheduled during the time I was in therapy and the game ui is disabled. This caused the game to irrecoverably stall for me on a fade-out (blank screen) after the dream movie finished playing; I was fortunately able to alt-tab out of Fallout 2 and end the program.
I obtained some relief from this problem by devolving all of Hakunin's movies-- which is also generally a helpful practice for any modder making a TC of FO2 that doesn't involve Hakunin's dream messages. All one needs do is create several completely empty text files in one's Fallout2\data\art\cuts\ folder named artimer1.mve, artimer2.mve, artimer3.mve, and artimer4.mve. Artimer1-4's cfg files should be edited as well to read:
Code:
[info]
total_effects=0 ; Total number of fading effects.
effect_frames=0,0 ; The frame number each effect will start on.
;
;
[0] ; Frame number this effect starts on.
fade_type=in ; Fade in or out?
fade_color=0,0,0 ; r,g,b value to fade from/to (range is 0-63).
fade_steps=0 ; number of steps (frames) this fade takes.
[240] ; Frame number this effect starts on.
fade_type=out ; Fade in or out?
fade_color=0,0,0 ; r,g,b value to fade from/to (range is 0-63).
fade_steps=0 ; number of steps (frames) this fade takes.
The result is beneficial in that no irrelevant movie is actually seen by the player; in this very peculiar case, however, since the movie was called while coincidentally the game ui was already disabled there are still remaining effects of the call for the movie-- which is the part I don't know how to fix myself. When the screen faded back in and the ui was re-enabled after receiving the doctor's therapy, I had no mouse cursor available; though the conversation seemed stuck, in fact keyboard input was still an option. Thus when reading:
DG: How do you feel? Are you OK?
PC: Ung... Blhgh... Ah...
I had to press the "1" key on my keyboard (to choose dialogue response option 1); after this the mouse cursor reappeared and the game thereafter functioned normally-- with one exception. The exception was that after completely finishing the post-therapy conversation with Goya, when the dialogue screen closed the game returned to a fade-out screen (presumably still running consequent to the call for Hakunin's movie). In this case, simply clicking anywhere on the screen resulted in a fade-in and a return to completely normal gameplay with no further issues.
Hence the root of the problem apparently is the conjunction of an interruption in the game's ui when the call for the dream-sequence is made during a ui-lockout while the player is receiving Goya's therapy. Again, the problem is not insurmountable (after ridding oneself of the actual display of the movies), but rather repugnant nonetheless as I suspect most folks would think the game solidly crashed at that point.
Regarding (b), while fiddling around investigating the problem already mentioned I saw a few trivial bugs in 0egoya.int. From habit (after all, I follow the modding forum because I enjoy modding) I also did a substantial amount of "bulletproofing" and general optimizing of the script (as well as to 0einvisc.int) that result in what I feel provides a much better assurance of intended functionality. Note as well while reading the code below (Ruby format), I was having trouble readily following the conversation constructed with gsay_options so I changed most of those to giq_options for convenience (the end result is the same, of course).
I made the following changes (thoroughly tested in all outcome iterations) to 0egoya.int:
--In what follows, the original contents of node016 and node017 were combined into a revised node015. Node997 in the original script is frivolous as it presently does nothing bar engender confusion in some script compilers, but my own best guess at its likely intended function was incorporated into node020. Hence all three aforementioned nodes are now redundant, but were left in place to avoid disrupting the nature of the original script (which again relies heavily on gsay_option calls).
--I see no need to reprint the entire lengthy "experiment" procedure here, but starting with the check of the "show" variable when such equals "3" I replaced everything in the remainder of the procedure with the following code. Note that I also made a decision for myself which is contrary to what Ardent apparently intended in the rare case where the player-character gets addicted to Jet; Ardent had an additional game-time advance at the end of the node so that in such a case, all the effects of Jet wear off before play resumes. I felt since this is an integral result of the therapy, the player-character should experience an additional side-effect after returning to consciousness while still dripping with fluid from the suspension tank-- but anyone who feels dissimilarly need only add an additional bit of game-time advancement right after the call to metarule 100.
Completely off-topic, by the way, when are our community's diligent frm modders going to get to work on some nekkid people? Yes, I know, make them myself... Prurient interests aside however, this is a genuine case (leaving the suspension tank) where a minimal A/B/C/R male and female tribal frm series would likely garner significant and widespread congratulation from anyone who experienced the result directed towared any modder willing to make the effort. Since an artfid change could be easily scripted and enforced, there need be no resulting concerns about rampant exhibitionism and lewdness.
Code:
else if (show == 3) then
begin
op_gfade_out(1000);
op_game_time_advance(3 * (7 * (24 * (60 * (60 * 10)))));
k := op_random(1, 100);
if ((op_get_critter_stat(op_dude_obj(), 2) <= 7) and (op_get_critter_stat(op_dude_obj(), 6) <= 7) != 0) then
begin
if (k < 36) then
op_set_critter_stat(op_dude_obj(), 1, -1);
else if (k < 71) then
op_set_critter_stat(op_dude_obj(), 3, -1);
else if (k < 96) then
begin
op_set_critter_stat(op_dude_obj(), 6, -1);
op_critter_add_trait(op_dude_obj(), 0, 118, 1);
end
else
op_add_timer_event(invisc_ptr, 1, 0);
end
op_critter_add_trait(op_dude_obj(), 0, 78, 1);
if (op_msg_string(1491, 100) != 0) then
begin
m := op_random(1, 3);
if (m == 1) then
op_set_critter_stat(op_dude_obj(), 0, 1);
else if (m == 2) then
op_set_critter_stat(op_dude_obj(), 2, 1);
else if (m == 3) then
begin
op_set_critter_stat(op_dude_obj(), 0, 1);
op_set_critter_stat(op_dude_obj(), 2, 1);
end
end
show := 0;
op_set_global_var(464, 2);
op_metarule3(100, op_self_obj(), 1, 0);
op_set_obj_invisibility(op_dude_obj(), 0);
maybe_unlock_input();
call talk_p_proc();
end
end
In procedure node020, I replaced everything currently extant with the following (among other things the player now receives a more substantial notification of Jet addiction):
Code:
procedure node020
begin
if (op_msg_string(1491, 249) != 0) then
begin
if (op_global_var(464) == 4) then
begin
chem := op_create_object(53, 0, 0, -1);
op_add_mult_objs_to_inven(op_dude_obj(), chem, 3);
end
else if (op_global_var(464) == 6) then
begin
chem := op_create_object(326, 0, 0, -1);
op_add_mult_objs_to_inven(op_dude_obj(), chem, 1);
end
else if (op_global_var(464) == 7) then
begin
chem := op_create_object(259, 0, 0, -1);
op_add_mult_objs_to_inven(op_dude_obj(), chem, 3);
end
end
op_gsay_reply(1491, op_msg_string(1491, 240 + op_global_var(464)) + op_msg_string(1491, 248));
if (op_global_var(464) == 7) then
op_display_msg("You are now addicted to Jet!");
op_giq_option(1, 1491, 249, @node999, 50);
end
Though not at all necessary, for my own convenience (perhaps others following along to incorporate these fixes into their own game will be similarly helped) I slightly changed the following as well:
Code:
procedure node019
begin
op_gsay_reply(1491, op_msg_string(1491, 238) + op_msg_string(1491, 235 + op_global_var(464)));
op_giq_option(1, 1491, 243, @node020, 50);
end
procedure node018
begin
op_gsay_reply(1491, 236);
op_giq_option(1, 1491, 237, @node019, 50);
end
In nodes 13, 14, and 15, I recommend the following changes-- though only the change in node013 is truly necessary in light of my modification of procedure_experiment; the rest were largely for rigor as well as my own convenience in understanding the script:
Code:
procedure node015
begin
if (op_global_var(464) == 3) then
begin
if (op_msg_string(1491, 248) != 0) then
begin
if (op_get_critter_stat(op_dude_obj(), 34) == 0) then
op_gsay_reply(1491, op_msg_string(1491, 233) + op_msg_string(1491, 248));
else
op_gsay_reply(1491, op_msg_string(1491, 234) + op_msg_string(1491, 248));
end
op_giq_option(1, 1491, 249, @node999, 50);
end
else
begin
if (op_msg_string(1491, 235) != 0) then
begin
if (op_get_critter_stat(op_dude_obj(), 34) == 0) then
op_gsay_reply(1491, 231);
else
op_gsay_reply(1491, 232);
end
op_giq_option(1, 1491, 235, @node018, 50);
end
end
procedure node014
begin
op_gsay_reply(1491, 229);
op_giq_option(1, 1491, 230, @node015, 50);
end
procedure node013
begin
op_gfade_in(1000);
if (op_msg_string(1491, 101) != 0) then
begin
if ((op_get_critter_stat(op_dude_obj(), 2) >= 7) and (op_get_critter_stat(op_dude_obj(), 6) >= 7) != 0) then
op_set_global_var(464, 3);
else if (k < 36) then
op_set_global_var(464, 4);
else if (k < 71) then
op_set_global_var(464, 5);
else if (k < 96) then
op_set_global_var(464, 6);
else
begin
op_set_global_var(464, 7);
op_set_local_var(7, op_game_time() + (4 * (7 * (24 * (60 * (60 * 10))))));
end
end
op_gsay_reply(1491, 227);
op_giq_option(1, 1491, 228, @node014, 50);
end
While looking at 0einvisc.int pursuant to (a) above, I thought the timed_event procedure not necessarily best-designed to accomplish its purpose. I rewrote it as follows (thoroughly tested):
Code:
procedure timed_event_p_proc
begin
if (op_fixed_param() == 0) then
begin
if (op_global_var(296) == 0) then
begin
if (op_obj_is_carrying_obj(op_self_obj(), 259) == 0) then
begin
drug := op_create_object(259, 0, 0, -1);
op_add_mult_objs_to_inven(op_self_obj(), drug, 1);
end
jet := op_obj_carrying_pid_obj(op_self_obj(), 259);
op_use_obj_on_obj(jet, op_dude_obj());
op_metarule3(100, op_self_obj(), 0, 0);
op_add_timer_event(op_self_obj(), op_game_ticks(5), 0);
end
else
begin
op_metarule3(100, op_self_obj(), 0, 0);
op_add_timer_event(op_self_obj(), op_game_ticks(2), 1);
end
end
if (op_fixed_param() == 1) then
op_destroy_object(op_self_obj());
end
I found that resetting the timer at function 0 to anything less than 5 ticks could result in a multiple application of Jet while gvar 296 was being set by the engine.
In conclusion, I'd like to say again I found this mod very impressive-- highly entertaining and technically innovative. I offer congratulations to Ardent on a job thus far well-done, and I hope he'll eventually resume his work here since any additional content would I think be eagerly welcomed by anyone who has tried the demo.
Endocore