I might as well post the four Fallout 2 modding tutorials I recently made here. Big disclaimer: all of these are in tested-in-mapper-untested-in-game limbo and therefore (especially in the case of the party member one) should be taken with a grain of salt. So it's probably a good idea to read through the respective threads first should you want to use them.
Tutorial for adding party members
[spoiler:0c77f50845]I recently decided to give modding Fallout 2 another go and redid the hours-long routine of finding tutorials and modding tools, relearning them, etc. etc. Anyway, one recurring complaint has been that there aren't really any tutorials of intermediate difficulty. As in, there's the standard beginner stuff on compiling, and so on, and some very in depth stuff, but nothing on what you can actually do once you've set everything up in the first place. Specifically, there's (as far as I can tell) no tutorials on doing what everyone wants to do the second they start modding fallout: making weird extra party members and sending them into battle. The most common advice is to just copy what the designers did with existing party member x (which any beginner will know is nigh impossible).
Now, I'm not much more than a beginner myself, so part of the goal of this tutorial is to hopefully get some pointers on which step is wrong/unnecessary/whatever (hence the attempt part). Also, I'm assuming you already know the absolute basics. Anyway, without further ado:
Let's say you want to make Lucas in Arroyo (the fisticuffs guy) a potential party member, what to do?
1: Right now Lucas doesn't have his own prototype (he's just another villager, while party members need to be *unique*), so you need to go to the critter proto folder, copy the villager proto file (i.e. 00000003.pro) and rename this copy to an available slot (e.g. 00000484.pro), which you have to also add at the end of the critter.lst file. Problem is, right now the proto file still "thinks" it's the old one, so use FUCK or some other critter changing program and change the ID number to 484 (and any other parameters you want to change of course).
2: Now we should give this unique little prototype a name. Open the critrpid.h header file and add
Code:
#define PID_LUCAS (16777700)
(remember that pids are the proto number + 16777216)
3: Now go to the party.h header file and just start copying, only with lucas instead op party member x.
So, instead of
Code:
#define Sulik_Ptr party_member_obj(PID_SULIK)
you do
Code:
#define Lucas_Ptr party_member_obj(PID_LUCAS)
etc.
4: Now go to the individual script file (i.e. acfist.ssl in the mapper scripts) and add
Code:
#define lucas_joins_party party_add_self; \
critter_add_trait(self_obj,TRAIT_OBJECT,OBJECT_TEAM_NUM,TEAM_PLAYER)
and put lucas_joins_party at whichever point (e.g. in converstation) you want him to come in your party. Now put in some extra local variables you will need:
Code:
#define LVAR_WAITING (7)
#define LVAR_FOLLOW_DISTANCE (8)
#define LVAR_TEAM (9)
#define LVAR_Joined_Party_Before (14)
#define PARTY_NODE_X Node1000
Now add this line to the beginning of procedure map_enter_p_proc:
Code:
begin
party_member_map_enter;
if (Lucas_In_Party) then begin
//do nothing
end else... etc.
so he doesn't join the arroyo team everytime you enter a map. Then at critter_p_proc add
Code:
else if (Lucas_In_Party) then begin
if (party_is_waiting == false) then begin
party_member_follow_dude
end
end
to get him to follow you around. Then add this line to the beginning of talk_p_proc:
Code:
if ( ( Lucas_Ptr != 0 ) or ( party_is_waiting ) ) then begin
start_gdialog(NAME,self_obj,4,-1,-1);
gSay_Start;
call Node1000;
gSay_End;
end_dialogue;
end
This calls the party options screen we all love so much. Just copy the nodes 1000-1100 from an existing party member script (don't forget to also introduce them at the beginning of the script, i.e. procedure Node1000; etc.) and change the sultik_party_member_options (and similar) to party_member_default_options (same with the gear and follow variants).
Finally remove the
Code:
critter_add_trait(self_obj,TRAIT_OBJECT,OBJECT_AI_PACKET,AI_ARROYO_WARRIOR);
line, so that you can alter the ai through the party options later on.
Now you should be able to compile.
5: Go to the party.txt file and copy whichever existing party member you want him to resemble (i.e. in Lucas' case, Sulik) and add a new entry, changing the PID number and removing level up stuff so that you get:
Code:
[Party Member 26] ; pMLucas_PID
party_member_pid=16777700
area_attack_mode=always, sometimes, be_careful
attack_who=whomever_attacking_me, strongest, whomever, closest
best_weapon=melee, melee_over_ranged, ranged_over_melee, unarmed
chem_use=clean, stims_when_hurt_little, stims_when_hurt_lots, sometimes, anytime, always
distance=stay_close, charge, snipe, on_your_own, stay
run_away_mode=none, tourniquet, never
disposition=none, custom, defensive, aggressive, berserk
level_minimum=0
level_up_every=0
level_pids=-1
Of course, if you happen to want Lucas to be able to level up to a martial arts master later on, make some more protos, edit them in FUCK, and add each consecutive pid number to "level_pids".
6: Finally go into the mapper and replace Lucas' villager prototype with your new prototype, give him one of Sulik's AI's (i.e. Berserk or Aggressive or whatever, it's just the default setting you can change) and give him the acfist.int script again.
Now F8 and it should work swimmingly!
[/spoiler:0c77f50845]
Tutorial for scripting battles a la the Den Gang War or the Ghost Farm showdown
[spoiler:0c77f50845]Again the set up for this is the same as for the previous tutorial. When I began (and immediately stopped) modding fallout a few years ago I wanted to do two things: make new party members and put together fights like the one in the Den. Especially the latter completely baffled me (I couldn't even get critters to move I remember) and without any tutorials around I soon gave up. Because, in case you hadn't noticed, checking to see what the developers did with the Den battle is extremely disheartening (just open den.h and prepare for sensory overload). So here's a barebones tutorial on how to do more or less the same thing.
As with the previous tutorial, I note up front that I'm a beginner myself and hopefully veterans will show up to explain all the things I did wrong/could have done easier/should have done to avoid the game breaking. Also, again, it's assumed that you know the absolute basics.
Okay, so suppose I want to set things up so that salvatore's gang can either attack Bishop's Casino or Mordino's Casino en masse (the latter is included to demonstrate how cross-map attacks, like the ones in the Den and the Ghost Farm, take place).
1) Make a new global variable called SALVATORE_ATTACK, which will be the basis for our two attacks (value 1 will be the attack on Bishop, 2 the one on Mordino). Now have these triggered through whichever conversation options which make sense to you.
2) open the map scripts for the two maps we're going to use (newr1.ssl and newr2.ssl) and add these lines to the latter:
Code:
export variable bouncer1;
export variable bouncer2;
and this one to the former:
Code:
export variable bouncer3;
export variable bouncer4;
We will need these variables to give our brave Salvatore troopers something to attack in a minute (at least, if I understood things right, you can only have scripts attack *individual* objects, but if it's somehow possible to attack a random critter with a certain script or on a certain team, I'd love to hear about it).
3: open the Salvatore grunt script (salmen.ssl) and add the lines
Code:
import variable bouncer1;
import variable bouncer2;
import variable bouncer3;
import variable bouncer4;
Now, let's start with moving towards the Bishop casino. Unless I'm a particularly stupid person, scripting movement in Fallout 2 is a pain in the ass. Critters constantly get stuck in other animations which they won't get out of, so it's important to cancel these out. So here's what we do; we add this line to critter_p_proc:
Code:
if (global_var(GVAR_SALVATORE_ATTACK) == 1) and (local_var(LVAR_Attack_1) == 0) then begin
animate_run_to_tile(19899);
if art_anim(ANIM_stand) then begin
reg_anim_clear(self_obj);
animate_run_to_tile(19899);
end
Ignore the LVAR for the moment. What's important is that everytime the critter is being an asshole and standing still because somebody went through the door before him, the script forces him to stop being an asshole and get moving again. The tile number is just in front of the casino entrance (it can't be much further; for some reason npc's don't like being forced to move very far, so if you want to get further you need to script it in babysteps).
Now, before we script the actual attack we want the Salvatore grunts to have some backup from their two pals upstairs, so we add the line underneath:
Code:
if (self_elevation != 0) then begin
critter_attempt_placement(self_obj, 16535, 0);
end
which puts them neatly beneath the stairs. Now to have them attack the bouncers, add this beneath the previous line:
Code:
if
(self_tile == 19899) then begin
attack(bouncer1);
set_local_var(LVAR_Attack_1, 1);
end
end
The LVAR just makes sure that they don't move back to tile 19899 after the battle like a bunch of idiots, but you can leave it out if you want. Of course, nothing happens yet because "bouncer1" doesn't exist yet. So now we go to step
4: Open the bouncer script (nccasbou.ssl), import the same variables (bouncer1, bouncer2, etc.) as in the Salvatore script and add the following line to map_enter_p_proc:
Code:
if (map_first_run) and (cur_map_index == MAP_NEW_RENO_2) then begin
if (bouncer1 == 0) then begin
bouncer1 := self_obj;
set_local_var(LVAR_Bouncer_Num, 1);
end else if (bouncer2 == 0) then begin
bouncer2 := self_obj;
set_local_var(LVAR_Bouncer_Num, 2);
end
end else if (local_var(LVAR_Bouncer_Num) == 1) then begin
bouncer1 := self_obj;
end else if (local_var(LVAR_Bouncer_Num) == 2) then begin
bouncer2 := self_obj;
end
Here I just copied the system used for the "junkie_talker"s in the Den.
(Now, just a note if you want to script using the New Reno bouncers specifically; they have this weird thing (maybe it's just in the mapper) where the team allocation system (the Mordino and Bishop bouncers have the same script) doesn't really work. So unless you want to end up having the Salvatore boys fighting prostitutes, add extra team lines for Bishop in the one map and Mordino in the other just for good measure.)
Et voila, F8 and the Bishop attack should work swimmingly.
5: Now for the Mordino attack; the bouncers just need an extra line similar to the previous one (remember that the bouncers for both casinos share the same script):
Code:
else if (map_first_run) and (cur_map_index == MAP_NEW_RENO_1) then begin
if (bouncer3 == 0) then begin
bouncer3 := self_obj;
set_local_var(LVAR_Bouncer_Num, 3);
end else if (bouncer4 == 0) then begin
bouncer4 := self_obj;
set_local_var(LVAR_Bouncer_Num, 4);
end
end else if (local_var(LVAR_Bouncer_Num) == 3) then begin
bouncer3 := self_obj;
end else if (local_var(LVAR_Bouncer_Num) == 4) then begin
bouncer4 := self_obj;
end
6: Now it's time in the mapper to go to the Mordino casino map and put copies of all the Salvatore grunts somewhere near the exit grid. Now give these copies each the salmen.int script and fill up their inventories the same way as their alter egos in the other map.
7: Now add the following line in the Salvatore men script beneath map_enter_p_proc:
Code:
if (cur_map_index == MAP_NEW_RENO_2) and (global_var(GVAR_SALVATORE_ATTACK) == 2) then begin
set_obj_visibility(self_obj,1);
end
if (cur_map_index == MAP_NEW_RENO_2) and (global_var(GVAR_SALVATORE_ATTACK) != 2) then begin
set_obj_visibility(self_obj,0);
end
if (cur_map_index == MAP_NEW_RENO_1) and (global_var(GVAR_SALVATORE_ATTACK) != 2) then begin
set_obj_visibility(self_obj,1);
end
if (cur_map_index == MAP_NEW_RENO_1) and (global_var(GVAR_SALVATORE_ATTACK) == 2) then begin
set_obj_visibility(self_obj,0);
end
This makes sure that the Salvatore men in the Mordino casino map stay safely nonexistent until the Mordino attack sequence fires, and that the men in Salvatore's bar dissappear when this happens. Of course you can make this more sophisticated by transporting the player along with them like in the Den gang war, but none of that is strictly necessary: what's important is that whenever one alter ego is visible the other is invisible.
Finally, just add these lines to the critter_p_proc beneath the others for the second attack to become possible:
Code:
if (global_var(GVAR_SALVATORE_ATTACK) == 2) and (local_var(LVAR_Attack_2) == 0) and (cur_map_index == MAP_NEW_RENO_1) then begin
animate_run_to_tile(17495);
if art_anim(ANIM_stand) then begin
reg_anim_clear(self_obj);
animate_run_to_tile(17495);
end if
(self_tile == 17495) then begin
attack(bouncer3);
set_local_var(LVAR_Attack_2, 1);
end
end
And there you have it! It took me a lot of tinkering and a couple of the errors I'm not even a hundred percent clear on how I got past them, but it *seems* to work well now. Of course, I'll undoubtedly be set straight on this account.
After this I think the only other tutorial I'll make is for setting up new caravans (because you can always use more caravans).
EDIT: I forgot to mention that the most important way this approach differs from the ones used for the Den and the Ghost Farm is that you start out as an observer (like in the random encounter fights). To change that, just insert a line somewhere that (temporarily) changes the team of the Salvatore men to TEAM_PLAYER)[/spoiler:0c77f50845]
Tutorial for adding new caravans
[spoiler:0c77f50845]To conclude my trilogy of tutorials by beginners for beginners, here's one on caravans. My last tutorial didn't get a single comment; which, being an eternal optimist I interpreted as a sign that the tutorial was perfect and every veteran simply nodded his head approvingly while reading it.
As an aside, caravans were always something I was a bit dissappointed in in Fallout. I mean, they were a lot of fun, but they basically only existed as little more than a get rich quick scheme, whereas you would think a world where even plants and ants have mutated into giant killing machines, moving around from town to town would generally require armed caravans.
But anyway, let's say we want to make a caravan of trappers from Klamath to the Den, what do we do? As previously, I'm going to assume you understand the basics (this time I'm also going to assume you understand that whenever you add a new procedure/node/variable, you need to introduce it in the script).
1: There are no existing caravan routes from Klamath to the Den, so we need to make one in BHRNDDST.H. Start by adding the line:
Code:
#define WM_In_Klamath_Den(x,y) ((x >= 300) and (x <500>= 100) and (y <= 300))
Here we delineate the area in which our encounters will take place. Unless there's a worldmap with x and y coordinates lying around somewhere I don't know of, you just need to look at the city coordinates in city.txt to get an idea where you are on the world map (e.g. the example is a box with Klamath at the top left corner and the Den at the lower right corner). Also, check that the area doesn't overlap with an already existing one. Now for the route:
To the bottom of the file, add:
Code:
// Klamath --> Den, 1 Encounter Only
#define Klamath_Den_1_1_x (420)
#define Klamath_Den_1_1_y (175)
// Klamath --> Den, 2 Encounters
#define Klamath_Den_2_1_x (390)
#define Klamath_Den_2_1_y (150)
#define Klamath_Den_2_2_x (450)
#define Klamath_Den_2_2_y (250)
The x,y coordinates show where you end up on the world map if the caravan "fails", and which encounter is fired (so, since all the coordinates are within our Klamath to Den box, these are the encounters that are fired). You can of course have as many possible encounters as you like, but 2 sounds about right here.
2: Now for the encounters, go to BHRNDDST.SSL (so this time the script, not the header file) and add the line:
Code:
else if (WM_In_Klamath_Den(worldmap_xpos,worldmap_ypos)) then \
call The_Den_Encounter;
Now let's define the procedure The_Den_Encounter:
Code:
procedure The_Den_Encounter begin
variable Encounter;
Encounter:=random(0,99);
// enc_00
if (Encounter < 50) then begin
debug_msg("Klamath_Encounter Table, Encounter 01");
display_msg(mstr(403));
Encounter_Counter:=random(8,12);
Encounter_Rotation:=dude_cur_rot;
call Klamath_Rats;
end
// enc_01
else if (Encounter < 100) then begin
debug_msg("Den_Encounter Table, Encounter 01");
display_msg(mstr(501));
Encounter_Counter:=random(1,3);
Encounter_Rotation:=dude_cur_rot;
call Klamath_Robbers;
end
end
I've kept it simple here: there's two possible encounters (50/50 chance) on the caravan: klamath_rats and klamath_robbers, which we'll get to in a second. Encounter_Counter is what determines how many critters show up, though you shouldn't mistake it for the exact number (e.g. in this example, there won't be 8-12 rats). To see what it does mean, let's set up the Klamath_Rats procedure:
Code:
procedure Klamath_Rats begin
variable Critter_Counter:=0;
variable Critter_Total;
//variable Critter;
variable Critter_Tile;
variable item;
Critter_Tile:=tile_num_in_direction(tile_num(dude_obj),Encounter_Rotation,dude_perception*2);
Critter_Total:=(Encounter_Counter*2)/5;
Critter_Counter:=0;
if (Critter_Total < 1) then
Critter_Total:=1;
while (Critter_Counter < Critter_Total) do begin
Create_Enemy(PID_MOLE_RAT,-1,SCRIPT_ECRAT);
inc_map_var(MVAR_Hostile_Total);
end
Critter_Total:=(Encounter_Counter*4)/5;
Critter_Counter:=0;
if (Critter_Total < 1) then
Critter_Total:=1;
while (Critter_Counter < Critter_Total) do begin
Create_Enemy(PID_PIG_RAT,-1,SCRIPT_ECRAT);
inc_map_var(MVAR_Hostile_Total);
end
end
Suppose the Encounter_Counter comes out as 10, then the outcome will be 10*2/5 = 4 mole rats and 10*4/5 = 8 pig rats, so twelve in total (in case you're wondering, non-round numbers get rounded down).
The thing I still can't get a handle on is how critters are placed. In this example, we defined Encounter_Rotation as dude_cur_rot so with
Code:
Critter_Tile:=tile_num_in_direction(tile_num(dude_obj),Encounter_Rotation,dude_perception*2);
you'd expect the enemies to get placed in front of where the player is facing; instead they end up all over the place. If anyone can tell me why I'd love to know.
3: Now to set up the caravan. First, make a global variable called TRAPPER_CARAVAN. Then, in the script of the trappers in Trapper Town (kctrapr.ssl), add the Start_Caravan procedure and have it called through dialogue or something:
Code:
procedure StartCaravan begin
variable Caravan_Carts;
variable Caravan_Encounters;
variable Caravan_Guards;
set_global_var(GVAR_CARAVAN_START, CARAVAN_KLAMATH);
set_global_var(GVAR_CARAVAN_END, CARAVAN_THE_DEN);
set_global_var(GVAR_TRAPPER_CARAVAN,CARAVAN_STATUS_ON_JOB);
set_caravan_status(CARAVAN_STATUS_ON_JOB);
Caravan_Encounters := random( 0, 2 );
set_caravan_encounters( Caravan_Encounters );
//debug_msg("ENCOUNTERS=" + k);
if (global_var(GVAR_CARAVAN_ENCOUNTERS_TOTAL) == 0) then begin
Caravan_Guards := 1;
set_caravan_guards( Caravan_Guards );
game_time_advance(6*ONE_GAME_DAY);
load_map(MAPSTR_DEBBUS1,0);
end
else begin
Caravan_Carts:=1;
Caravan_Guards:=0;
set_caravan_masters(1);
set_caravan_guards( Caravan_Guards );
set_caravan_carts( Caravan_Carts );
set_caravan_brahmin( 2 * Caravan_Carts );
set_caravan_drivers( 2 * Caravan_Carts );
load_map(MAPSTR_BHRNDDST,11); //<-robs map script ignores this index...must be above 10
//however to put caravan in center of map
end
end
As you can deduce, this caravan goes from Klamath to the Den, with 0 to 2 encounters (if you want more you need to add the coordinates to the header file in step 1), one caravan master, one cart (how many gecko pelts can they have), two brahmin, and two drivers.
4: Now, go back to BHRNDDST.ssl and add the following line to map_enter_p_proc:
Code:
else if (global_var(GVAR_TRAPPER_CARAVAN) == CARAVAN_STATUS_ON_JOB) then begin
call Trapper_Caravan;
end
For the Trapper_Caravan procedure:
Code:
procedure Trapper_Caravan begin
variable Encounter_Number;
call Klamath_Den_Encounters;
call Build_Caravan_Team;
end
Now, scroll down to the Build_Caravan_Team procedure. For my example, I just tried to replicate the three trappers in Trapper Town, but you can do whatever you feel like of course. For instance, for the first caravan driver I used:
Code:
else if (global_var(GVAR_TRAPPER_CARAVAN) == CARAVAN_STATUS_ON_JOB) then begin
Critter:=create_object_sid(PID_MALE_TRAPPER,0,0,SCRIPT_RCCVNGRD);
add_obj_to_inven(Critter,create_object(PID_10MM_JHP,0,0));
item:=create_object(PID_SPRINGER_RIFLE,0,0);
end
This creates the leather jacket trapper with a pipe rifle (wielded) and some rounds. This is different from the system the script usually uses, which is in the form of a random male/female of a certain type, with a random weapon chosen from a few options. To simply copy this system is risky given that most models only support a few types of weapons. So, for instance, if I had used this system with either male or female trapper, with either a spear or a pipe gun, then the female trapper could end up with a pipe gun she couldn't use (because of no animation being there).
Finally, just add one additional procedure:
Code:
procedure Klamath_Den_Encounters begin
variable Encounter_Number;
Encounter_Number:=total_encounters - encounters_left;
if (total_encounters == 1) then begin
set_caravan_pos(Klamath_Den_1_1_x,Klamath_Den_1_1_y);
set_exit_grids(0,-2,0,20100,0); // Exit grids on elevation 0 goto Worldmap
game_time_advance(6*ONE_GAME_DAY);
check_area;
end
else if (total_encounters == 2) then begin
if (Encounter_Number == 0) then begin // this is the first encounter
set_caravan_pos(Klamath_Den_2_2_x,Klamath_Den_2_2_y);
set_exit_grids(0,-2,0,20100,0); // Exit grids on elevation 0 goto Worldmap
game_time_advance(3*ONE_GAME_DAY);
check_area;
end
else if (Encounter_Number == 1) then begin // this is the second encounter
set_caravan_pos(Klamath_Den_2_1_x,Klamath_Den_2_1_y);
set_exit_grids(0,-2,0,20100,0); // Exit grids on elevation 0 goto Worldmap
game_time_advance(3*ONE_GAME_DAY);
check_area;
end
end
end
The only additional thing this really does in practice is let you decide the time that elapses between encounters.
And there you have it.
[/spoiler:0c77f50845]
Tutorial for scripting a change in character models
[spoiler:0c77f50845]Designating a specific object while modding Fallout 2 is quite annoying (imagine how nice it would be to be able to do so in the mapper). I already pointed out the basics for doing so in my
tutorial for making a battle script, but that assumed you didn't care *which* of a number of critters carrying the same script became a certain object. That is to say, we had 4 bouncers in that example, and we simply wanted to number them bouncer1, bouncer2, etc. without caring which of them became which. But what if you *do* want to specify that?
For instance, suppose you have Jordan in Arroyo (the one always twirling his spear), and you want to "power him up" at one point in the game for some reason, e.g. by making him into a leather armored proto. In this case, you want to put the new proto next to him on the map, and then make the one go invisible as the other becomes visible, right? But if you only have one script for the both of them (i.e. acjordan.ssl), then how do you do this (making a new script is a very sloppy workaround, because all the changes in local variables get lost)?
The method I found most feasible (though others might of course have better ones), is to check for equiped weapons. So the Jordan with the spear becomes "jordan1" and the Jordan with a powered up weapon (e.g. a sharpened spear) becomes "jordan2".
This way you can script it as follows (as you'll see, the only other thing you need is some global variable to trigger the "powering up"). Under map_enter_p_proc add something along the lines of:
Code:
if (map_first_run) then begin
if obj_carrying_pid_obj(self_obj, PID_SPEAR) then begin
jordan1 := self_obj;
end
if obj_carrying_pid_obj(self_obj, PID_SHARP_SPEAR) then begin
jordan2 := self_obj;
end
end
if (self_obj == jordan1) and (global_var(GVAR_ARROYO_SLAVERS) == SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 1);
end
if (self_obj == jordan2) and (global_var(GVAR_ARROYO_SLAVERS) != SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 1);
end
if (self_obj == jordan1) and (global_var(GVAR_ARROYO_SLAVERS) != SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 0);
end
if (self_obj == jordan2) and (global_var(GVAR_ARROYO_SLAVERS) == SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 0);
end
The map_first_run thing is necessary to avoid a scenario where Jordan throws his spear, doesn't pick it up, and turns invisible when you come back to the map (not terribly likely, I know, but might as well rule it out). When you want to use the same trick only with multiple carriers of the same script, for instance to beef up all the Arroyo warriors, then all you need is a combination of the method used for the bouncers in New Reno and the method outlined above. After all, for all the warriors within their respective groups (i.e. the "beefed up group" and the "un-beefed up group) we don't have to be specific (they are all either invisible or visible); we only need to differentiate between the two groups. So what you get is (again under map_enter_p_proc):
Code:
if (map_first_run) then begin
if (warrior1 == 0) and obj_carrying_pid_obj(self_obj, PID_SPEAR) then begin
warrior1 := self_obj;
end else if (warrior2 == 0) and obj_carrying_pid_obj(self_obj, PID_SPEAR) then begin
warrior2 := self_obj;
end else if (warrior3 == 0) and obj_carrying_pid_obj(self_obj, PID_SPEAR) then begin
warrior3 := self_obj;
end else if (warrior4 == 0) and obj_carrying_pid_obj(self_obj, PID_SPEAR) then begin
warrior4 := self_obj;
end else if (warrior11 == 0) and obj_carrying_pid_obj(self_obj, PID_10MM_PISTOL) then begin
warrior11 := self_obj;
end else if (warrior21 == 0) and obj_carrying_pid_obj(self_obj, PID_SHOTGUN) then begin
warrior21 := self_obj;
end else if (warrior31 == 0) and obj_carrying_pid_obj(self_obj, PID_10MM_SMG) then begin
warrior31 := self_obj;
end else if (warrior41 == 0) and obj_carrying_pid_obj(self_obj, PID_COMBAT_KNIFE) then begin
warrior41 := self_obj;
end
end
if (self_obj == warrior1) and (global_var(GVAR_ARROYO_SLAVERS) == SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 1);
end
if (self_obj == warrior11) and (global_var(GVAR_ARROYO_SLAVERS) != SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 1);
end
if (self_obj == warrior1) and (global_var(GVAR_ARROYO_SLAVERS) != SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 0);
end
if (self_obj == warrior11) and (global_var(GVAR_ARROYO_SLAVERS) == SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 0);
end
if (self_obj == warrior2) and (global_var(GVAR_ARROYO_SLAVERS) == SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 1);
end
if (self_obj == warrior21) and (global_var(GVAR_ARROYO_SLAVERS) != SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 1);
end
if (self_obj == warrior2) and (global_var(GVAR_ARROYO_SLAVERS) != SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 0);
end
if (self_obj == warrior21) and (global_var(GVAR_ARROYO_SLAVERS) == SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 0);
end
if (self_obj == warrior3) and (global_var(GVAR_ARROYO_SLAVERS) == SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 1);
end
if (self_obj == warrior31) and (global_var(GVAR_ARROYO_SLAVERS) != SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 1);
end
if (self_obj == warrior3) and (global_var(GVAR_ARROYO_SLAVERS) != SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 0);
end
if (self_obj == warrior31) and (global_var(GVAR_ARROYO_SLAVERS) == SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 0);
end
if (self_obj == warrior4) and (global_var(GVAR_ARROYO_SLAVERS) == SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 1);
end
if (self_obj == warrior41) and (global_var(GVAR_ARROYO_SLAVERS) != SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 1);
end
if (self_obj == warrior4) and (global_var(GVAR_ARROYO_SLAVERS) != SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 0);
end
if (self_obj == warrior41) and (global_var(GVAR_ARROYO_SLAVERS) == SL_DEAL_SEALED) then begin
set_obj_visibility(self_obj, 0);
end
And there you have it.[/spoiler:0c77f50845]