Unequip and equip items - unreliable

I have had this issue for a long time now. I’ve mostly ignored it and taken it for what it is, but I’m beginning to get fed up with it. Whenever I use ga_equip_slot and ga_unequip_slot, or I do a custom script with the functions Unequipslot and ActionEquipItem, it is almost always unreliable. It works for about 75 % of the time but one can never be sure of it.

Recently, I had such a situation where I really need the whole party to unequip some shovels, and most of the time, only one of them do this. I guess it’s about things that can interupt the code…or something. Is there a “bulletproof” way to use these functions? Here’s how I did it in a conversation but only one of the companions unequips the shovel:

//ga_unequippartyhands - script by andgalf

#include "ginc_item"

void main()
{

object oPC = GetFirstPC();

object oFM = GetFirstFactionMember(oPC);

	while (GetIsObjectValid(oFM))
	{
		AssignCommand(oFM, ClearAllActions());
		UnequipSlot(oFM, INVENTORY_SLOT_LEFTHAND);
		UnequipSlot(oFM, INVENTORY_SLOT_RIGHTHAND);
		oFM = GetNextFactionMember(oPC);

	}



}

What I noticed when the ActionEquipItem failed me when I really needed it to work flawlessly (the equipping of the shovels), I instead used the EquipNewItem(oFM,"shovel",INVENTORY_SLOT_RIGHTHAND);, and that for some reason made it work every time. So my guess is that there are very particular ways of doing these scripts to make them work? I mean, even the stock scripts ga_equip_slot and ga_unequip_slot are unreliable.

Not:

GetNextFactionMember(object oMemberOfFaction, int bPCOnly=TRUE);

But:

oFM = GetNextFactionMember(oPC,FALSE);

Or you won’ t catch your companions but only player charaters. So only the first one unequip the showel beceause the loop only call the action for it, since it’s the only player character.

Alright, so that’s what that meant in the description of the function. Fair enough.

This still doesn’t explain that ga_equip_slot and ga_unequip_slot doesn’t always work though.

items needs to be identified, the actions queue is limited and must’nt be disturbed after beeing assigned, but there are others disturber.

1 Like

Alright, this is obiously quite tricky since there seems to be a lot that can interfer with an action. I managed to script something that kind of works now.

Here’s a question: If say the player clicks on some place on the ground to make the character go there, is there some code to make the game pause that action, do some other stuff (since we enter a trigger in that path) and then resume the action afterwards? The way I do it now is to use clear all actions, but that means the player has to click again on the point he/she wanted to go to. It would have been nice to not have to do that.

@Lance_Botelle - You don’t know any about that perhaps?

@andgalf

In this case, I would recommend scripting a cutscene where you take control of the PC actions to perform each step, and then release control back to the player once all your steps have been completed.

The event would be triggered (or captured by you to start the cutscene) when the player enters a trigger en route when they first click to move to a certain spot.

1 Like

it can get really tricky, so here’s a trick …

//AssignCommand(oPC, ClearAllActions()); // this should not be needed

AssignCommand(oPC, doAction());
AssignCommand(oPC, doAction());

// this happens after all Actions complete (make it the last Action in the queue)
// this turns the execution of a function into an Action on the PC's actionqueue
AssignCommand(oPC, ActionDoCommand(SetCommandable(TRUE, oPC)));

// and since this is not an Action it happens before the actionqueue
// the engine will execute it before the above Actions!
// Player can no longer break the actionqueue until SetCommandable(TRUE)
// happens above.
SetCommandable(FALSE, oPC);

it’s just a trick; it won’t help if something other than player-intervention is breaking things. This just stops player from, for example, clicking to move before a scripted sequence of Actions completes, which would clear the actionqueue and thereby wipe all scripted actions.

other than this i don’t feel comfortable suggesting what to do since getting a sequence of actions/events to happen robustly ingame tends to be, as you noticed very finicky,

 
I think i got that sequence of commands right, haven’t used it in a long time …

2 Likes

Eh…I’m trying to read your post several times here, @kevL_s but I’m not following. I’m just confused at the moment.

Uugh, I think I’ll just post my whole script here (even though I don’t like that since now I’m beginning to spoil my module by telling exactly what happens, but nevermind…it’s not a big thing, I guess.):

MINOR SPOILERS FOR MY UPCOMING MODULE (will not be released until a year from now probably)

//kevL_s' version of my script. Shorter and more compact and easier to follow also, I guess.
//I've added and changed stuff now and some additional code that I didn't post on the vault at the time.  /andgalf

#include "ginc_item"

const int APPEARANCE_TYPE_YUANTIPUREBLOOD      = 40;

const int APPEARANCE_TYPE_ASSIMAR              = 563;
const int APPEARANCE_TYPE_TIEFLING             = 564;
const int APPEARANCE_TYPE_ELF_SUN              = 565;
const int APPEARANCE_TYPE_ELF_WOOD             = 566;
const int APPEARANCE_TYPE_ELF_DROW             = 567;
const int APPEARANCE_TYPE_GNOME_SVIRFNEBLIN    = 568;
const int APPEARANCE_TYPE_DWARF_GOLD           = 569;
const int APPEARANCE_TYPE_DWARF_DUERGAR        = 570;
const int APPEARANCE_TYPE_HALFLING_STRONGHEART = 571;

const int APPEARANCE_TYPE_ELF_WILD             = 1036;
const int APPEARANCE_TYPE_GENASI_EARTH         = 1037;
const int APPEARANCE_TYPE_GENASI_FIRE          = 1038;
const int APPEARANCE_TYPE_GENASI_AIR           = 1039;
const int APPEARANCE_TYPE_GENASI_WATER         = 1040;
const int APPEARANCE_TYPE_HALFDROW             = 1041;

void Swimming()
{

	object oPC1 = GetFirstPC();
	
	object oNelowyn = GetObjectByTag("nelowync");
	object oGnome = GetObjectByTag("gnome");
	object oLania = GetObjectByTag("leniac");
	object oSemaphine = GetObjectByTag("semaphine");
	object oTindra = GetObjectByTag("tindra");
	object oFleksa = GetObjectByTag("fleksac");
	
		int iApp; //Short for Appearance. I wouldn't have called it this if this were my own code. /andgalf

	switch (GetAppearanceType(oPC1))
	{
		case APPEARANCE_TYPE_DWARF: iApp = 4000; break; // Dwarf_swim
		case 4000: iApp = APPEARANCE_TYPE_DWARF; break;

		case APPEARANCE_TYPE_ELF: iApp = 4001; break; // Elf_swim
		case 4001: iApp = APPEARANCE_TYPE_ELF; break;

		case APPEARANCE_TYPE_GNOME: iApp = 4002; break; // Gnome_swim
		case 4002: iApp = APPEARANCE_TYPE_GNOME; break;

		case APPEARANCE_TYPE_HALFLING: iApp = 4003; break; // Halfling_Swim
		case 4003: iApp = APPEARANCE_TYPE_HALFLING; break;

		case APPEARANCE_TYPE_HALF_ELF: iApp = 4004; break; // Half_Elf_Swim
		case 4004: iApp = APPEARANCE_TYPE_HALF_ELF; break;

		case APPEARANCE_TYPE_HALF_ORC: iApp = 4005; break; // Half_Orc_Swim
		case 4005: iApp = APPEARANCE_TYPE_HALF_ORC; break;

		case APPEARANCE_TYPE_HUMAN: iApp = 4006; break; // Human_Swim
		case 4006: iApp = APPEARANCE_TYPE_HUMAN; break;

		case APPEARANCE_TYPE_ASSIMAR: iApp = 4007; break; // Assimar_Swim
		case 4007: iApp = APPEARANCE_TYPE_ASSIMAR; break;

		case APPEARANCE_TYPE_TIEFLING: iApp = 4008; break; // Tiefling_Swim
		case 4008: iApp = APPEARANCE_TYPE_TIEFLING; break;

		case APPEARANCE_TYPE_ELF_SUN: iApp = 4009; break; // Elf,Sun_Swim
		case 4009: iApp = APPEARANCE_TYPE_ELF_SUN; break;

		case APPEARANCE_TYPE_ELF_WOOD: iApp = 4010; break; // Elf,Wood_Swim
		case 4010: iApp = APPEARANCE_TYPE_ELF_WOOD; break;

		case APPEARANCE_TYPE_ELF_DROW: iApp = 4011; break; // Elf,Drow_Swim
		case 4011: iApp = APPEARANCE_TYPE_ELF_DROW; break;

		case APPEARANCE_TYPE_GNOME_SVIRFNEBLIN: iApp = 4012; break; // Gnome,Svirfneblin_Swim
		case 4012: iApp = APPEARANCE_TYPE_GNOME_SVIRFNEBLIN; break;

		case APPEARANCE_TYPE_DWARF_GOLD: iApp = 4013; break; // Dwarf,Gold
		case 4013: iApp = APPEARANCE_TYPE_DWARF_GOLD; break;

		case APPEARANCE_TYPE_DWARF_DUERGAR: iApp = 4014; break; // Dwarf,Duergar_Swim
		case 4014: iApp = APPEARANCE_TYPE_DWARF_DUERGAR; break;

		case APPEARANCE_TYPE_HALFLING_STRONGHEART: iApp = 4015; break; // Halfling,Strongheart_Swim
		case 4015: iApp = APPEARANCE_TYPE_HALFLING_STRONGHEART; break;

		case APPEARANCE_TYPE_ELF_WILD: iApp = 4016; break; // Elf_Wild_NX1_Swim
		case 4016: iApp = APPEARANCE_TYPE_ELF_WILD; break;

		case APPEARANCE_TYPE_GENASI_EARTH: iApp = 4017; break; // Earth_Genasi_NX1_Swim
		case 4017: iApp = APPEARANCE_TYPE_GENASI_EARTH; break;

		case APPEARANCE_TYPE_GENASI_FIRE: iApp = 4018; break; // Fire_Genasi_NX1_Swim
		case 4018: iApp = APPEARANCE_TYPE_GENASI_FIRE; break;

		case APPEARANCE_TYPE_GENASI_AIR: iApp = 4019; break; // Air_Genasi_NX1_Swim
		case 4019: iApp = APPEARANCE_TYPE_GENASI_AIR; break;

		case APPEARANCE_TYPE_GENASI_WATER: iApp = 4020; break; // Water_Genasi_NX1_Swim
		case 4020: iApp = APPEARANCE_TYPE_GENASI_WATER; break;

		case APPEARANCE_TYPE_HALFDROW: iApp = 4021; break; // Half_Drow_NX1_Swim
		case 4021: iApp = APPEARANCE_TYPE_HALFDROW; break;

		case APPEARANCE_TYPE_YUANTIPUREBLOOD: iApp = 4022; break; // YuantiPureblood_Swim
		case 4022: iApp = APPEARANCE_TYPE_YUANTIPUREBLOOD; break;

		default: return;
	}

		SetCreatureAppearanceType(oPC1, iApp);
		
			if(GetFactionEqual(oPC1,oNelowyn))
	{
		if(GetAppearanceType(oNelowyn) == 4006)
		{
	
		SetCreatureAppearanceType(oNelowyn,APPEARANCE_TYPE_HUMAN);
	
		}

		else if(GetAppearanceType(oNelowyn) == APPEARANCE_TYPE_HUMAN)
		{
	
		SetCreatureAppearanceType(oNelowyn,4006);
	
		}
	
	}	
	
	if(GetFactionEqual(oPC1,oLania))
	{
		if(GetAppearanceType(oLania) == 4006)
		{
	
		SetCreatureAppearanceType(oLania,APPEARANCE_TYPE_HUMAN);
	
		}

		else if(GetAppearanceType(oLania) == APPEARANCE_TYPE_HUMAN)
		{
	
		SetCreatureAppearanceType(oLania,4006);
	
		}
	
	}	
	
	if(GetFactionEqual(oPC1,oFleksa))
	{
		if(GetAppearanceType(oFleksa) == 4006)
		{
	
		SetCreatureAppearanceType(oFleksa,APPEARANCE_TYPE_HUMAN);
	
		}

		else if(GetAppearanceType(oFleksa) == APPEARANCE_TYPE_HUMAN)
		{
	
		SetCreatureAppearanceType(oFleksa,4006);
	
		}
	
	}	
	
	if(GetFactionEqual(oPC1,oTindra))
	{
		if(GetAppearanceType(oTindra) == 4006)
		{
	
		SetCreatureAppearanceType(oTindra,APPEARANCE_TYPE_HUMAN);
	
		}

		else if(GetAppearanceType(oTindra) == APPEARANCE_TYPE_HUMAN)
		{
	
		SetCreatureAppearanceType(oTindra,4006);
	
		}
	
	}	
	
	if(GetFactionEqual(oPC1,oSemaphine))
	{
		if(GetAppearanceType(oSemaphine) == 4006)
		{
	
		SetCreatureAppearanceType(oSemaphine,APPEARANCE_TYPE_HUMAN);
	
		}

		else if(GetAppearanceType(oSemaphine) == APPEARANCE_TYPE_HUMAN)
		{
	
		SetCreatureAppearanceType(oSemaphine,4006);
	
		}
	
	}	
	
	if(GetFactionEqual(oPC1,oGnome))
	{
		if(GetAppearanceType(oGnome) == 4002)
		{
	
		SetCreatureAppearanceType(oGnome,APPEARANCE_TYPE_GNOME);
	
		}

		else if(GetAppearanceType(oGnome) == APPEARANCE_TYPE_GNOME)
		{
	
		SetCreatureAppearanceType(oGnome,4002);
	
		}
	
	}	
	
}

void main()
{
	object oPC = GetEnteringObject();
	object oPC1 = GetFirstPC();
	object oPC2 = GetFirstPC(FALSE);

	if (!GetIsPC(oPC)) return;
	
	SetCutsceneMode(oPC1);
		
	object oFM = GetFirstFactionMember(oPC1,FALSE);

	while (GetIsObjectValid(oFM))
	{
		AssignCommand(oFM,ClearAllActions());	
		UnequipSlot(oFM, INVENTORY_SLOT_LEFTHAND);
		UnequipSlot(oFM, INVENTORY_SLOT_RIGHTHAND);
		UnequipSlot(oFM, INVENTORY_SLOT_CLOAK);
	
		oFM = GetNextFactionMember(oPC1,FALSE);

	}
	
	SetCutsceneMode(oPC1,FALSE);
	
	DelayCommand(1.0,Swimming());
	
	
	

}

So, the situation is this in detail. We are at a shore. There’s a tiny island. You click on that island to go there, and by going there you pass through a trigger with this script, which turns the characters into swimming characters. I want to make sure that they have no weapons in their hands or cloak on them when they begin swimming. Right now it works, but since I do a ClearAllActions the game doesn’t remember the player clicking on the island.

I have a way of doing it, I suppose, by making the characters moving to a waypoint that’s probably close to where the player clicked, but if that could be avoided I would be happy.

What will be happening in this instance is that the player clicks on the island first (most probably), then enters a trigger where the script runs, and then I would have wanted the game to proceed with the moving to where the player clicked.

SetCommandable(TRUE, oPC);
AND
SetCommandable(FALSE, oPC);

This is what I mean by making it a cutscene. :slight_smile:

1 Like

Ok. Well, as you see in the script I use SetCutScenemode which is almost the same thing, I guess. So I don’t thinkt that changes much…

“Click on island” …You can take control from this point. You can capture the location click, I believe - or maybe that is an issue? :thinking:. (*) And I imagine you can add a delay at which point to change the animation from the time of initial click rather than use an additional trigger.

Just tie all your actions between the SetCommandable function, which is set at the initial click.

(*) Maybe you can have a conversation begin to ask if player wants to swim across on the initial click, and/or just assume the landing location with a WP as I believe you initially suggested.

OR … here is something similar to what I use in my latest module … Have a rock or old post sticking out the bank where the PC is to swim to and call it “swim to” or something like that. Make sure they cannot use it when on that side! Clicking on that then starts the “cutscene” actions.

Hmmm. Yeah, that could work, actually…

You can capture a location click? That would be awesome. At the moment I changed my script to this and it actually worked quite well (even if the waypoint at the shore isn’t quite what the player clicked at it’s no biggie I realized since the player can immediately change the point since I’m not forcing anything when the party has gotten into the water).

//kevL_s' version of my script. Shorter and more compact and easier to follow also, I guess.
//I've added and changed stuff now and added some additional code that I didn't post on the vault at the time.  /andgalf

#include "ginc_item"

const int APPEARANCE_TYPE_YUANTIPUREBLOOD      = 40;

const int APPEARANCE_TYPE_ASSIMAR              = 563;
const int APPEARANCE_TYPE_TIEFLING             = 564;
const int APPEARANCE_TYPE_ELF_SUN              = 565;
const int APPEARANCE_TYPE_ELF_WOOD             = 566;
const int APPEARANCE_TYPE_ELF_DROW             = 567;
const int APPEARANCE_TYPE_GNOME_SVIRFNEBLIN    = 568;
const int APPEARANCE_TYPE_DWARF_GOLD           = 569;
const int APPEARANCE_TYPE_DWARF_DUERGAR        = 570;
const int APPEARANCE_TYPE_HALFLING_STRONGHEART = 571;

const int APPEARANCE_TYPE_ELF_WILD             = 1036;
const int APPEARANCE_TYPE_GENASI_EARTH         = 1037;
const int APPEARANCE_TYPE_GENASI_FIRE          = 1038;
const int APPEARANCE_TYPE_GENASI_AIR           = 1039;
const int APPEARANCE_TYPE_GENASI_WATER         = 1040;
const int APPEARANCE_TYPE_HALFDROW             = 1041;

void MoveToLocation()
{

	object oPC1 = GetFirstPC(FALSE);
	object oWaypoint = GetObjectByTag("backtoshorewp");
	
	location lLocation = GetLocation(oWaypoint);
	AssignCommand(oPC1, ActionMoveToLocation(lLocation,TRUE));

}


void Swimming()
{

	object oPC1 = GetFirstPC();
	
	object oNelowyn = GetObjectByTag("nelowync");
	object oGnome = GetObjectByTag("gnome");
	object oLania = GetObjectByTag("leniac");
	object oSemaphine = GetObjectByTag("semaphine");
	object oTindra = GetObjectByTag("tindra");
	object oFleksa = GetObjectByTag("fleksac");
	
		int iApp; //Short for Appearance. I wouldn't have called it this if this were my own code. /andgalf

	switch (GetAppearanceType(oPC1))
	{
		case APPEARANCE_TYPE_DWARF: iApp = 4000; break; // Dwarf_swim
		case 4000: iApp = APPEARANCE_TYPE_DWARF; break;

		case APPEARANCE_TYPE_ELF: iApp = 4001; break; // Elf_swim
		case 4001: iApp = APPEARANCE_TYPE_ELF; break;

		case APPEARANCE_TYPE_GNOME: iApp = 4002; break; // Gnome_swim
		case 4002: iApp = APPEARANCE_TYPE_GNOME; break;

		case APPEARANCE_TYPE_HALFLING: iApp = 4003; break; // Halfling_Swim
		case 4003: iApp = APPEARANCE_TYPE_HALFLING; break;

		case APPEARANCE_TYPE_HALF_ELF: iApp = 4004; break; // Half_Elf_Swim
		case 4004: iApp = APPEARANCE_TYPE_HALF_ELF; break;

		case APPEARANCE_TYPE_HALF_ORC: iApp = 4005; break; // Half_Orc_Swim
		case 4005: iApp = APPEARANCE_TYPE_HALF_ORC; break;

		case APPEARANCE_TYPE_HUMAN: iApp = 4006; break; // Human_Swim
		case 4006: iApp = APPEARANCE_TYPE_HUMAN; break;

		case APPEARANCE_TYPE_ASSIMAR: iApp = 4007; break; // Assimar_Swim
		case 4007: iApp = APPEARANCE_TYPE_ASSIMAR; break;

		case APPEARANCE_TYPE_TIEFLING: iApp = 4008; break; // Tiefling_Swim
		case 4008: iApp = APPEARANCE_TYPE_TIEFLING; break;

		case APPEARANCE_TYPE_ELF_SUN: iApp = 4009; break; // Elf,Sun_Swim
		case 4009: iApp = APPEARANCE_TYPE_ELF_SUN; break;

		case APPEARANCE_TYPE_ELF_WOOD: iApp = 4010; break; // Elf,Wood_Swim
		case 4010: iApp = APPEARANCE_TYPE_ELF_WOOD; break;

		case APPEARANCE_TYPE_ELF_DROW: iApp = 4011; break; // Elf,Drow_Swim
		case 4011: iApp = APPEARANCE_TYPE_ELF_DROW; break;

		case APPEARANCE_TYPE_GNOME_SVIRFNEBLIN: iApp = 4012; break; // Gnome,Svirfneblin_Swim
		case 4012: iApp = APPEARANCE_TYPE_GNOME_SVIRFNEBLIN; break;

		case APPEARANCE_TYPE_DWARF_GOLD: iApp = 4013; break; // Dwarf,Gold
		case 4013: iApp = APPEARANCE_TYPE_DWARF_GOLD; break;

		case APPEARANCE_TYPE_DWARF_DUERGAR: iApp = 4014; break; // Dwarf,Duergar_Swim
		case 4014: iApp = APPEARANCE_TYPE_DWARF_DUERGAR; break;

		case APPEARANCE_TYPE_HALFLING_STRONGHEART: iApp = 4015; break; // Halfling,Strongheart_Swim
		case 4015: iApp = APPEARANCE_TYPE_HALFLING_STRONGHEART; break;

		case APPEARANCE_TYPE_ELF_WILD: iApp = 4016; break; // Elf_Wild_NX1_Swim
		case 4016: iApp = APPEARANCE_TYPE_ELF_WILD; break;

		case APPEARANCE_TYPE_GENASI_EARTH: iApp = 4017; break; // Earth_Genasi_NX1_Swim
		case 4017: iApp = APPEARANCE_TYPE_GENASI_EARTH; break;

		case APPEARANCE_TYPE_GENASI_FIRE: iApp = 4018; break; // Fire_Genasi_NX1_Swim
		case 4018: iApp = APPEARANCE_TYPE_GENASI_FIRE; break;

		case APPEARANCE_TYPE_GENASI_AIR: iApp = 4019; break; // Air_Genasi_NX1_Swim
		case 4019: iApp = APPEARANCE_TYPE_GENASI_AIR; break;

		case APPEARANCE_TYPE_GENASI_WATER: iApp = 4020; break; // Water_Genasi_NX1_Swim
		case 4020: iApp = APPEARANCE_TYPE_GENASI_WATER; break;

		case APPEARANCE_TYPE_HALFDROW: iApp = 4021; break; // Half_Drow_NX1_Swim
		case 4021: iApp = APPEARANCE_TYPE_HALFDROW; break;

		case APPEARANCE_TYPE_YUANTIPUREBLOOD: iApp = 4022; break; // YuantiPureblood_Swim
		case 4022: iApp = APPEARANCE_TYPE_YUANTIPUREBLOOD; break;

		default: return;
	}

		SetCreatureAppearanceType(oPC1, iApp);
		
			if(GetFactionEqual(oPC1,oNelowyn))
	{
		if(GetAppearanceType(oNelowyn) == 4006)
		{
	
		SetCreatureAppearanceType(oNelowyn,APPEARANCE_TYPE_HUMAN);
	
		}

		else if(GetAppearanceType(oNelowyn) == APPEARANCE_TYPE_HUMAN)
		{
	
		SetCreatureAppearanceType(oNelowyn,4006);
	
		}
	
	}	
	
	if(GetFactionEqual(oPC1,oLania))
	{
		if(GetAppearanceType(oLania) == 4006)
		{
	
		SetCreatureAppearanceType(oLania,APPEARANCE_TYPE_HUMAN);
	
		}

		else if(GetAppearanceType(oLania) == APPEARANCE_TYPE_HUMAN)
		{
	
		SetCreatureAppearanceType(oLania,4006);
	
		}
	
	}	
	
	if(GetFactionEqual(oPC1,oFleksa))
	{
		if(GetAppearanceType(oFleksa) == 4006)
		{
	
		SetCreatureAppearanceType(oFleksa,APPEARANCE_TYPE_HUMAN);
	
		}

		else if(GetAppearanceType(oFleksa) == APPEARANCE_TYPE_HUMAN)
		{
	
		SetCreatureAppearanceType(oFleksa,4006);
	
		}
	
	}	
	
	if(GetFactionEqual(oPC1,oTindra))
	{
		if(GetAppearanceType(oTindra) == 4006)
		{
	
		SetCreatureAppearanceType(oTindra,APPEARANCE_TYPE_HUMAN);
	
		}

		else if(GetAppearanceType(oTindra) == APPEARANCE_TYPE_HUMAN)
		{
	
		SetCreatureAppearanceType(oTindra,4006);
	
		}
	
	}	
	
	if(GetFactionEqual(oPC1,oSemaphine))
	{
		if(GetAppearanceType(oSemaphine) == 4006)
		{
	
		SetCreatureAppearanceType(oSemaphine,APPEARANCE_TYPE_HUMAN);
	
		}

		else if(GetAppearanceType(oSemaphine) == APPEARANCE_TYPE_HUMAN)
		{
	
		SetCreatureAppearanceType(oSemaphine,4006);
	
		}
	
	}	
	
	if(GetFactionEqual(oPC1,oGnome))
	{
		if(GetAppearanceType(oGnome) == 4002)
		{
	
		SetCreatureAppearanceType(oGnome,APPEARANCE_TYPE_GNOME);
	
		}

		else if(GetAppearanceType(oGnome) == APPEARANCE_TYPE_GNOME)
		{
	
		SetCreatureAppearanceType(oGnome,4002);
	
		}
	
	}	
	
}

void main()
{
	object oPC = GetEnteringObject();
	object oPC1 = GetFirstPC();
	
	if (!GetIsPC(oPC)) return;
	
	SetCutsceneMode(oPC1);
		
	object oFM = GetFirstFactionMember(oPC1,FALSE);

	while (GetIsObjectValid(oFM))
	{
		AssignCommand(oFM,ClearAllActions());	
		UnequipSlot(oFM, INVENTORY_SLOT_LEFTHAND);
		UnequipSlot(oFM, INVENTORY_SLOT_RIGHTHAND);
		UnequipSlot(oFM, INVENTORY_SLOT_CLOAK);
	
		oFM = GetNextFactionMember(oPC1,FALSE);

	}
	
	SetCutsceneMode(oPC1,FALSE);
	
	DelayCommand(1.0,Swimming());
	
	DelayCommand(1.2,MoveToLocation());
	

}

I just looked at the GetClickingObject and GetLastPlaceableClickedBy. That’s all good and well but not the way I wanted since I would have liked to get the location and not a specific object or placeable.

Actually, I believe I ended up just using the “post” idea because I could not capture the player click point as well I as liked to. Hence my suggestion … now I have given a spoiler (minor) of mine too. :wink: I don’t have animations involved though. :wink: Basically, I used “posts” to indicate specific swim to locations rather than larger unspecified locations.

I think I’ll go with what I have now since it worked better than expected, and it’s at least as good as if I had a “clicking post” to swim to.

Hello,

this is my approach to a 120% reliable unequip (developed with diamond, not tested).

If you desperate enough, try it out :slight_smile:

This goes to the user defined events of the area.

void WegDamit (object p, int s)
{
object i = GetItemInSlot (s, p);
if (!GetIsObjectValid(i)) return;
CopyItem (i, p, TRUE);
DestroyObject (i);
}

void main()
{
if (GetUserDefinedEventNumber() != 4711) return;

object oPC = GetLocalObject (OBJECT_SELF, “Unequipper”);
object oFm = GetFirstFactionMember (oPC, FALSE);
while (GetIsObjectValid (oFm))
{
WegDamit (oFm, INVENTORY_SLOT_LEFTHAND);
WegDamit (oFm, INVENTORY_SLOT_RIGHTHAND);
oFm = GetNextFactionMember (oPC, FALSE);
}
}

The whole thing is launched by a ground trigger:

void main()
{
object oPC = GetEnteringObject();
object a = GetArea (oPC);

SetLocalObject (a, “Unequipper”, oPC);
SignalEvent (a, EventUserDefined (4711));
DestroyObject (OBJECT_SELF, 1.0);
}

Have fun!

1 Like

Thanks, I might try it sometime, though at the moment I have a “bulletproof” system in the current scene I’m working on right now. The secret is/was to make sure that no actions are interrupting other actions and in what order to do things. Quite tricky but obviously doable when I got down to it.

:slight_smile:

The secret is/was to make sure that no actions are interrupting other actions

Fine, that’s what my code is doing.