Fair Strides

Fair Strides' Script Shack

Recommended Posts

Thanks for your help!! I fixed it by changing it to this:

ActionMoveToLocation(Location(Vector(-77.5775390625, -51.8112106323242, 0.0), 213.749927975663), 0));

I don't know if it actually works as intended but it compiled, so.

Share this post


Link to post
Share on other sites

How would I go about starting a conversation after killing a group of people? Like when Canderous and his mercenaries along with Revan and his party killed the Rakghouls in the Undercity before Canderous joined them.

 

(K1 Script).

 

Another thing, how can I "lock" a party member and make them required to be in your party for the time being?

Share this post


Link to post
Share on other sites

Kreia uses the animation during the Jedi Enclave Scene so I'll hope it's a General Animation.

It has a bunch of requirements. You should probably check Visas' entry on the Ravager (with 1.8.5) to see them, it alters a bunch of stuff if failing to prevent the scene from looking really stupid, so whatever you do, it runs proper. Took a bit of tweaking to make both look good, but I'm confident it was successful and paid of that work.

Share this post


Link to post
Share on other sites

It has a bunch of requirements. You should probably check Visas' entry on the Ravager (with 1.8.5) to see them, it alters a bunch of stuff if failing to prevent the scene from looking really stupid, so whatever you do, it runs proper. Took a bit of tweaking to make both look good, but I'm confident it was successful and paid of that work.

So what type of requirements are these? If it matters I am trying to get the Batu Rem imposter to do it with a Vibrosword when he reaches 1HP then immediately after he does the seppuku he dies and grenn runs in and does his usual conversation (Painfully obvious what this is for). 

Share this post


Link to post
Share on other sites

Umm, any idea how I could warp the player in the Hawk and trigger a conversation? 

Share this post


Link to post
Share on other sites

To warp the character you just need

void main(){

SetGlobalBoolean("EH_WARP", TRUE);
StartNewModule(<name of the ebon hawk module with quotes>, <optional waypoint tag with quotes>);

}

Replace <...> with the appropriate string. This will warp the player to the specified waypoint on the Ebon Hawk. If you don't specify a waypoint, it'll use the default one. The setting of the global boolean is necessary to make sure that the conversation is triggered only in this case. Replace it's name with something you like and add it to globalcat.2da

 

Then we need to start the conversation on board the Ebon Hawk. To do that, you can either modify the OnEnter script or create your own trigger. In any case, the added script part would look something like this:

object oEnter = GetEnteringObject();
object oDialogPartner = GetObjectByTag(<Add dialog partner tag with quotes>);

if(oEnter == GetFirstPC() && GetGlobalBoolean("EH_WARP")) {
AssignCommand(oDialogPartner, ActionStartConversation(GetFirstPC(), <dialog tag with quotes>));
SetGlobablBoolean("EH_WARP", FALSE);
}

This of course needs to be inside the void main() {} of either the OnEnter or the trigger script. Once again, replace the <...> with the appropriate strings and the boolean name.

The two conditions are to make sure that the dialog only starts when the player enters and that it only starts when warped here with the first script.

Share this post


Link to post
Share on other sites

To warp the character you just need

void main(){

SetGlobalBoolean("EH_WARP", TRUE);
StartNewModule(<name of the ebon hawk module with quotes>, <optional waypoint tag with quotes>);

}

Replace <...> with the appropriate string. This will warp the player to the specified waypoint on the Ebon Hawk. If you don't specify a waypoint, it'll use the default one. The setting of the global boolean is necessary to make sure that the conversation is triggered only in this case. Replace it's name with something you like and add it to globalcat.2da

 

Then we need to start the conversation on board the Ebon Hawk. To do that, you can either modify the OnEnter script or create your own trigger. In any case, the added script part would look something like this:

object oEnter = GetEnteringObject();
object oDialogPartner = GetObjectByTag(<Add dialog partner tag with quotes>);

if(oEnter == GetFirstPC() && GetGlobalBoolean("EH_WARP")) {
AssignCommand(oDialogPartner, ActionStartConversation(GetFirstPC(), <dialog tag with quotes>));
SetGlobablBoolean("EH_WARP", FALSE);
}

This of course needs to be inside the void main() {} of either the OnEnter or the trigger script. Once again, replace the <...> with the appropriate strings and the boolean name.

The two conditions are to make sure that the dialog only starts when the player enters and that it only starts when warped here with the first script.

Thanks!

Share this post


Link to post
Share on other sites

Two questions from me today:

 

First of all, in the documentation for GetPartyMemberByIndex(int nIndex) it is stated that this should return the party leader for nIndex = 0 and the two party members for nIndex = 1 & 2:

// 577: Returns the party member at a given index in the party.
// The order of members in the party can vary based on
// who the current leader is (member 0 is always the current
// party leader).
// GetPartyMemberByIndex
object GetPartyMemberByIndex(int nIndex);

However, this seems to be wrong as I've been using it to get party members 1 and 2 and it only gives a useful result (the second party member) for nIndex = 1. To get the first party member, I need to use nIndex = 0. I was wondering if anyone knows if that's how it always works as I doubt that it's intended. I'm assuming that as this is the reason for the second party member spawning in the main hall in the hostile Korriban academy instead of in it's appropriate position.

 

The second question is somewhat weird. I've been testing that scene where you enter the hostile Korriban academy to find what's causing the incorrect spawn point and as stated above, I found the culprit. However, I thought the issue was somewhere else for a while which is why I had a closer look at the script spawning the party members upon entering the academy after retrieving the starmap. It's the OnEnter script for korr_m35aa, called kor35_enter. Here's the relevant part:

int nGlobal = GetGlobalNumber("KOR_FINAL_TEST");
		if (((nGlobal > 3) && (!sub6()))) {
			SetGlobalBoolean("KOR_ADD_PARTY", 1);
			sub8(1);
			int int18;
			int int19;
			string string1;
			int18 = 0;
			while ((int18 < GetGlobalNumber("KOR_REMOVE_PCS"))) {
				int19 = GetGlobalNumber(("KOR_REMOVE_PC" + IntToString(int18)));
				sub5(((("KOR_REMOVE_PC" + IntToString((int18 - 1))) + ":") + IntToString(int19)), (6 + int18), (6 + int18), 5.0);
				switch (int19) {
					case 0:
						string1 = "Bastila";
						break;
					case 1:
						string1 = "Cand";
						break;
					case 2:
						string1 = "Carth";
						break;
					case 3:
						string1 = "HK47";
						break;
					case 4:
						string1 = "Jolee";
						break;
					case 5:
						string1 = "Juhani";
						break;
					case 6:
						string1 = "Mission";
						break;
					case 7:
						string1 = "T3M4";
						break;
					case 8:
						string1 = "Zaalbar";
						break;
				}
				AddPartyMember(int19, GetObjectByTag(string1, 0));
				(int18++);
			}

You can ignore all the subX() functions as they are either for debugging or not related to spawn NPCs. As you can see, the game will check KOR_REMOVE_PCS which should be the number of party members that got removed when leaving for the final tomb. It's set in k_pkor_partyleav and it's actually incorrectly set to the number of removed party members + 1, but that's not the issue here. The game will then go through KOR_REMOVE_PC0 to KOR_REMOVE_PC2 depending on the number of NPCs that got removed (although, it goes one step to far due to the incorrect KOR_REMOVE_PCS). These three globals are also set in k_pkor_partyleav and contain the party member indices of the removed NPCs and KOR_REMOVE_PC2 is just 0 as there is no third NPC to remove from the party (which makes me wonder, if at some point you had three companions at once). The game will then save this index in int19 and assing the proper string in string1 to spawn the NPC with AddPartyMember.

Now, this is obviously working, but as soon as I change the values of KOR_REMOVE_PC0 or KOR_REMOVE_PC1 with KSE, that NPC just won't spawn for some reason. The only two party members that will spawn are Canderous and Juhani, the two party members that should spawn in my playthrough without tinkering. However, they also spawn if I switch their positions in the globals, which makes me wonder what the hell is going on here. All I can confirm is that both the index and the string are assigned correctly, so it seems that it's the AddPartyMember that fails. I just don't know why...

Then again, it's not actually a problem as it seems to work fine in vanilla and when not using KSE to alter these two globals and I have no intentions of altering that part of the script. I'd just like to know what's going on.

 

Thanks for any help :)

  • Like 1

Share this post


Link to post
Share on other sites

Regarding the nindex numbers, though I don't do modding or scripting, I gather from what you posted that it has to do with how the code (script maybe) sees numbers. I've learned a little bit of Python, so someone correct me if I'm wrong. In code, 0 is considered a number and, I think, is considered the first number in numerical sequence. I think it's due to Binary. But I can't remember the exact reason. I've been trying to Google it, and can't find the answer.

 

If I'm right, then the answer is "Yes. That's how it always works."

 

The other part is beyond me. My only guess is there is something else resetting the global that you are changing. I had something similar happen to me. I kept trying to change something, but the game just wouldn't have it.

Share this post


Link to post
Share on other sites

I'm trying to remake some feats from K2 and put them in K1. Right now I'm working through scripting the Close Combat tree of feats. My operative question is: how often does the k_hen_attacked01 script run? Does it run every time a single attacker attacks you (so, multiple times per round if you're being swarmed by enemies), or does it only run once each round?

I currently have script drafted for the heartbeat script, but it might be more efficient (read: not need a looping statement) if I the k_hen_attacked01 script runs for each attacker of the party member.

 

This isn't perfect, but my drafted heartbeat script to run the feat for a single character is:

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//	Close Combat Lvl 4
//
//	This really probably belongs directly in this script once I figure out the logic. Actually,
//	maybe it belongs in OnAttacked?
//
//	What should count as close range? 2 meters? Womp rats aren't much bigger than 2 meters.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
integer iParty0RH==0;

integer iAttack0RH==0;

integer iCCBonus0==0;

integer iCCDetriment0==0;

if (GetHasFeat(****, oParty0)==1) {
	iCCBonus0==2;
	iCCDetriment0==4;
else if (GetHasFeat(***,oParty0)==1) {
	iCCBonus0==1;
	iCCDetriment0==2;
}

if (GetWeaponRanged(GetItemInSlot(oParty0, INVENTORY_SLOT_RIGHTHAND))==1) {iParty0RH==1}

//	Party Member 0		//
if (GetHasFeat(****, oParty0) && (iParty0RH==1)) {
	do {
		if (GetWeaponRanged(GetItemInSlot(oAttack0, INVENTORY_SLOT_RIGHTHAND))==1) {iAttack0RH==1}
	
		if (iAttack0RH!=1) {	
			ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAttackDecrease(iCCDetriment0, ATTACK_BONUS_MISC, oAttack0, 6.0);
			
			if (GetAttackTarget(oParty0)==oAttack0) {
				ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAttackIncrease(iCCBonus0, ATTACK_BONUS_ONHAND) oParty0, 6.0);
				ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAttackIncrease(iCCBonus0, ATTACK_BONUS_OFFHAND) oParty0, 6.0);			
			}
		}
	}
		oAttack0==GetNextAttacker(oParty0);
	while (oAttack0!=(GetLastAttacker(oParty0)));
}

Share this post


Link to post
Share on other sites

Im new to scriping. Is there a good resource for a crash course? And how difficult would it be to have a script that equips an item to a pc or npc when a feat is selected/gained upon leveling up?

Share this post


Link to post
Share on other sites

KoTOR Scripting Tool is very useful, you can download it here: http://deadlystream.com/forum/files/file/191-kotor-scripting-tool/

 

There's also a bunch of resources online if you google NWScript, the language the game uses for scripting.

 

The biggest problem I would see with your idea is how you attach it to leveling up. You could easily run something in the k_hen_heartbeat01 script and have it run once if it meets your conditions. Say you want to give Atton a lightsaber in his right hand when he gets the lightsaber proficiency ability, your script might look something like:

Declare a global variable:
     integer nHasThisRunBefore==0;

Then, in the k_hen_heartbeat01 script:

void main () {
     if (GetHasFeat(FEAT_WEAPON_PROFICIENCY_LIGHTSABER, GetObjectByTag("Atton")) && (nHasThisRunBefore==0) && (GetFirstPC()==GetObjectByTag("Atton"))) {
          ActionGiveItem("g_w_lghtsbr[01-11].uti", GetObjectByTag("Atton"));
          ActionEquipItem("g_w_lghtsbr[01-11], INVENTORY_SLOT_RIGHTHAND);

          nHasThisRunBefore==1;
     }
}

You could then copy the script into the k_hen_heartbeat01 script, compile it, and put it into the override folder. Then when Atton becomes a Jedi and gets the lightsaber proficiency feat (and is the party leader), he would get a lightsaber of a color you specify [01-11] in his right hand inventory slot. 

  • Like 1

Share this post


Link to post
Share on other sites

My hopes were more to have dummy "feats" as options in the game UI, and use some already created items be granted into the invisible slots. Ive so far created 3 feat items for each starting class as a beginning, and have room for 4? feat lines via the hidden slots. Know what I mean?

Share this post


Link to post
Share on other sites

There's not actually a way to directly create new feats, they're hard coded into the system. There are ways you can work around that for passive feats, but you can't script a dummy feat that runs directly on level up. At least, I don't know a way to do it. Though, that's not saying much.

Share this post


Link to post
Share on other sites

Can one that simply appears in the feat menu not be created? It doesn't actually have to do anything. I've seen a mod that adds feats via the heartbeat script. As long as it can show up in the UI duing level up to be selected and is then able to fulfill the "if (GetHasFeat(CUSTOM_FEAT, GetObjectByTag("Atton"))" part of the script to equip a premade item with the feat's modifiers attached to it into the invisible slots then I'm happy. If it's not a "true feat" or whatever really doesn't matter to me, as long as the intended result occurs.

Share this post


Link to post
Share on other sites

I've read that weapon proficiency feats can be made. Could an item be a "weapon" that becomes equipped after a custom proficiency feat is taken? The description for that feat would still be like "Gain Massive Criticals 1d8" but in actuality an item granting that modifier was simply equipped to the PC/NPC and no real feat was ever gained.

Share this post


Link to post
Share on other sites

I want to place a background NPC in a module in K1 and have it stand in place performing a single looping animation. I gather I'll need to make a custom appearance with a model that uses a renamed version of the animation I want, so I can call it via script with the limited constants available. That part is fine. The question is how to get it to play the animation? Do I add that to the creature's OnSpawn script?

 

I also have a couple of other NPCs that I want to fight each other in the background. From poking through other threads it seems like the easiest solution is to set their factions to Predator and Prey and enable the Min 1 HP flag. What about OnSpawn and other scripts for them? Do they need any? Generic ones?

Share this post


Link to post
Share on other sites

I want to place a background NPC in a module in K1 and have it stand in place performing a single looping animation. I gather I'll need to make a custom appearance with a model that uses a renamed version of the animation I want, so I can call it via script with the limited constants available. That part is fine. The question is how to get it to play the animation? Do I add that to the creature's OnSpawn script?

 

I also have a couple of other NPCs that I want to fight each other in the background. From poking through other threads it seems like the easiest solution is to set their factions to Predator and Prey and enable the Min 1 HP flag. What about OnSpawn and other scripts for them? Do they need any? Generic ones?

 

You don't want to use the OnSpawn script as that's only fired the first time the character is spawned, i.e. when first entering the module. If you leave and come back later, it won't be fired again so your animation won't play either. So you'd probably use the OnHeartbeat script (I did for my Full Jedi Council mod and it worked out).

 

And I don't know about the second question. Maybe they need a script that tells them to start attacking each other, but if I were to guess I'd say you're fine without them. Keeping the generic standard scripts wouldn't hurt though I guess.

Share this post


Link to post
Share on other sites

So I should take default heartbeat template, which appears to be k_def_heartbt01:

void main()
{
    ExecuteScript("k_ai_master", OBJECT_SELF, KOTOR_DEFAULT_EVENT_ON_HEARTBEAT);
}
and add the command to that? And what would that consist of? I gather I need to include something along the lines of

AssignCommand(GetObjectByTag("CREATURE_TAG"), ActionPlayAnimation(######, 1.0, -1.0f));

Share this post


Link to post
Share on other sites

As your character is only a background character that doesn't need to behave like an NPC you could even skip the ExecuteScript line and just use this:

void main(){

AssignCommand(OBJECT_SELF, ActionPlayAnimation(####, 1.0, -1.0));

}

OBJECT_SELF refers to the object running the script which would allow you to use the script on multiple characters without having to make a unique script calling the correct tag for each of them.

Share this post


Link to post
Share on other sites

Cheers, I'll give that a whirl.

 

I'll try the fighters with just default scripts and see what the faction setting does. I did try to see how they did the sparring sequence with Bastila in the training montage on Dantooine, but in the relevant DLG I could only see scripts that equipped and unequipped the swords, not anything that actually controlled the animations of the cutscene.

 

Edit: That all seems to work. Thanks again. Now I just need to make some adjustments to positioning and facing, and turn off the labels on the fighters (getting rid of the names is easy enough, but the health bars seem problematic).

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.