Question about moving companions across modules [RESOLVED]

Since I’ve had problems with my soon to be released module with quite a few CTDs (sadly it will be released with this, since I can’t seem to do anything about it now), I thought that I would try and do all in my power to prevent this for my next module. I think this whole thing is a memory issue, with me maybe using too many areas in a module or too many companions in the party at one time, I don’t know.

To try and fix things, or at least make things better, I thought I would try to do my new campaign consisting of multiple modules (like 3 or so). However, the way I’ve gone about things before is to always place the different companions in an area. I know this isn’t the way it’s supposed to be done, but it has worked for me. But if I’m to do a campaign consisting of multiple modules I think I would need to really use the spawning system (or something similar) that the OC uses. I’ve again looked at Colorsfade’s Companion System (his and @andysks pdf) and in there he tells me that one needs to use the function SaveRosterLoadModule() that is found in the include ginc_companion. What I don’t quite understand is WHERE do I put this function for things to work? It’s not clear in the PDF. Do I put it in the OnModuleLoad of the first module or where? To my understanding this must be called when switching from one module to another. I can’t find any OnModuleExit slot though so… Can someone explain this to me?

EDIT: Maybe I should just do a custom script that I call when jumping to an area in a new module, if I have a New Area Transition trigger I can use the script there, or in a conversation I put that same script there?

Before calling either LoadNewModule() or StartNewModule() call DespawnAllRosterMembers(int bPreserveParty=FALSE);

 
perhaps … im not too familiar with what the actual/wider ramifications are … but am pretty sure that’s what it means.

that’s basically what the official modules do … but they went wholehog setting up waypoint prefixes etc etc and designing a generic transition script for all of them. And id say it’s a good idea to set up your own script for doing transitions, one that you become familiar with … but note

- ga_load_mod : uses SaveRosterLoadModule(sModule, sWaypoint);
- ga_start_mod : uses StartNewModule(sModule);

@kevL_s - Thanks for the reply! So…I could use the ga_load_mod then? Or do I need the ga_start_mod too? Not quite following you here… (I need both functions?)

EDIT: And I need to do the DespawnAllRosterMembers before this?
EDIT2: Maybe I’ll just fiddle around with things, test them and hope things work. Thankfully I haven’t gotten that far into my new module. Only about 45 min playtime if I’m to guess, so it’s maybe not that big of a deal, but I will need to be careful with all the scripts that I need, from Colorsfade’s suggestions. I have used his system before in my second module, but back then I had mostly no idea what I was doing when it came to scripts, and I encountered quite a few bugs, which made me abandon this system for future modules. I think I will (despite his claim to only use his scripts to not cause bugs) use my own scripts and methods and take a few things here and there from his suggestions, basically to really know what’s going on.

EDIT3: Would I need to make my companions campaign blueprints or is it ok to just use module blueprints? From what I can see in the OC, if I understand correctly, they are just module blueprints.

you need to divide your work on several module with one campaign to link them all.

In a module it’s better to stick to one major exterior area.

in général it’s better to have only one major area in a module, and all it’s conext and tiny area linked to it.

And when you move to an other major area, it’s better to have it in an other module.

the main goal of it is to reduce the load time.

As for CDT unless you do something really enormous you shouldn’t have them, when we released BGR we made a fondamental mistake, we put all the Baldur’s Gate city into a single module. The module is really énormous but it doesn’ t CDT.

Also you have to know as a module becomes bigger, it’s become more difficult to debug it, since it becommes more difficult to “cut” between events.

If you CDT the odd are more with the way you handle your companions with scripting.

Also I personnaly prefer to “spawn” as much as possible instead of “placing them”, the reason is that it’s so much easier to correct/modify something that isn’t spawned.

1 Like

I was going to have a hangout spot, a camp if you will, and Colorsfade suggests that the companions, when dismissing them, should be moved to this spot. Quite logical really. I’ve done things like this before in a similar way. However, now with having multiple modules, I think I can only have this area in one of the modules, correct? Can you really move the companions to an area that’s in another module?

EDIT: I was thinking of using JumpToObject like I’ve done before. Does this work when jumping to an area in another module under the same campaign?

You need to “cheat”.

In order to move a companion to an other module, well the truth is that you can’t.

You need to despawn your companion, and respawn it when the player enter the other module, it’s not automatic, you need to check when you enter the module, or your camp in your case if a companion needs to spawned or not.

And don’t make the mistake/bugI made with BGR, I am not sure it’s fully corrected in BGR, but when you remove a companion you need to use the roster function to despawn it, in order for it to be saved.

So companion needs to be handled with roster function, the risk if you don’t is to spawn a new “newbie” companion, and not the one the player had an history with.

Roster are tied to the player, so when you move accross different module it moves with the player. When you make companiosn roster member they becommes part of the “player object”. And when a roster member leaves you need to save in order to save its progression.

Alright, so if I understand this correctly, something like this would work?
When removing a companion (I used an old script that I now modified which has worked without problems before):

void main(string sRoster)
{
    object oPC = GetPCSpeaker();
			
    object oDestSabrina = GetWaypointByTag(sDEST_SABRINA);
	object oDestCatherine = GetWaypointByTag(sDEST_CATHERINE);
	object oDestNankun = GetWaypointByTag(sDEST_NANKUN);
	object oDestEsfiza = GetWaypointByTag(sDEST_ESFIZA);
	object oDestTeala = GetWaypointByTag(sDEST_TEALA);

	
	object oCompanion = GetObjectByTag(sRoster);
  		
		if (sRoster == "sabrina")
        {
            
            RemoveRosterMemberFromParty(sRoster, oPC, FALSE);
			DespawnRosterMember(sRoster);				
			//AssignCommand(oCompanion, ClearAllActions());
            //AssignCommand(oCompanion, JumpToObject(oDestSabrina));			
       
		}	
		
		else if (sRoster == "catherine")
        {
            
            RemoveRosterMemberFromParty(sRoster, oPC, FALSE);
			DespawnRosterMember(sRoster);				
			//AssignCommand(oCompanion, ClearAllActions());
            //AssignCommand(oCompanion, JumpToObject(oDestSabrina));


		}	
		
		else if (sRoster == "nankun")
        {
            
            RemoveRosterMemberFromParty(sRoster, oPC, FALSE);

            DespawnRosterMember(sRoster);				
			//AssignCommand(oCompanion, ClearAllActions());
            //AssignCommand(oCompanion, JumpToObject(oDestSabrina));

		}
		
		else if (sRoster == "esfiza")
        {
            
            RemoveRosterMemberFromParty(sRoster, oPC, FALSE);

            DespawnRosterMember(sRoster);				
			//AssignCommand(oCompanion, ClearAllActions());
            //AssignCommand(oCompanion, JumpToObject(oDestSabrina));

		}	
		
		else if (sRoster == "teala")
        {
            
            RemoveRosterMemberFromParty(sRoster, oPC, FALSE);

           	DespawnRosterMember(sRoster);				
			//AssignCommand(oCompanion, ClearAllActions());
            //AssignCommand(oCompanion, JumpToObject(oDestSabrina));


  
		}	
		
	
 
}

Then when entering the hangout area I use Colorsfade’s function on the OnClientEnter:

void PutCompanionInPlace(string sCompanionTag)
{
	object oPC = GetFirstPC();
	
	int bMetCompanion = GetHasMetCompanion(sCompanionTag);
	
	// If we haven't met the companion before, exit.
	if(!bMetCompanion)
	{
		return;
	}
		
	// If the companion isn't already in our party, then place them at 
	// their hangout waypoint. There should only be one of these per module!
	object oCompanion = GetObjectByTag(sCompanionTag);
	if(!GetIsObjectInParty(oCompanion))
	{
		// this call should not be necessary
		string sHangOutWP = "hangout_" + sCompanionTag;
		SetHangOutSpot(sCompanionTag, sHangOutWP);
		SpawnNonPartyRosterMemberAtHangout(sCompanionTag);
	}
}

Yup, something like that.

AddRosterMemberByCharacter or AddRosterMemberByTemplate


To make your character a roster member.


DespawnRosterMember

if not in party and leaving the area where the player is.


SpawnRosterMember

when you want it to show up again.

those are the key functions

1 Like

Did some testing and it actually seems to be working really well.