Note: LucasForums Archive Project
The content here was reconstructed by scraping the Wayback Machine in an effort to restore some of what was lost when LF went down. The LucasForums Archive Project claims no ownership over the content or assets that were archived on archive.org.

This project is meant for research purposes only.

Spawning Items, Placeables and Creatures

Page: 1 of 1
 RedHawke
01-26-2005, 7:30 PM
#1
Original Thread (http://www.lucasforums.com/showthread.php?s=&threadid=143436)
This tutorial is example-oriented, with Redhawke providing an example of spawning a locker with items inside. tk102 discusses how to prevent re-entry in the second post.

If you want to spawn your own Footlocker, try this;

Extract a game footlocker, remove any items from it's invantory and scripts from the scripts fields, then change the templateresref and resref to footlker099, then change it's tag to Footlocker99 then save the .utp file as footlker099.utp.

Here is the basic script to spawn a footlocker that uses the .utp you created above in the game and place some items into it, therefore you can use the same footlocker .utp all throughout the game and it all works the same as it is the script that denotes what is in the footlocker / metalbox / plastic cylender / etc.


//note this code allows for re-entry as-is,
// you should only attach it to a dialog
// that you know will only fire once.
// To prevent re-entry in a more general sense, see tk102's notes in the next post

void main()
{
vector MyVec;
MyVec.x = 0.00f; //Here is where you add the 'whereami' cheat coordinate 1.
MyVec.y = 0.00f; //Here is where you add the 'whereami' cheat coordinate 2.
MyVec.z = 0.00f; //Here is where you add the 'whereami' cheat coordinate 3 (elevation).
float r = 0.0f; // This is where you set the orientation of the placeable, set in degrees.

object oLocker = CreateObject( OBJECT_TYPE_PLACEABLE, "footlker099", Location(MyVec, r));

CreateItemOnObject("g_w_lghtsbr05", oLocker);
CreateItemOnObject("g_a_mstrrobe01", oLocker);
CreateItemOnObject("g_w_sbrcrstl04", oLocker, 2);
}


Another simplified way to write this code could be:

void main()
{
object oLocker=CreateObject( OBJECT_TYPE_PLACEABLE, "footlker099", Location(Vector(0.00,0.00,0.00), 0.0));

CreateItemOnObject("g_w_lghtsbr05", oLocker);
CreateItemOnObject("g_a_mstrrobe01", oLocker);
CreateItemOnObject("g_w_sbrcrstl04", oLocker, 2);
}



Copy this text paste it to notepad and then edit the file to taste, you will have to enter the coordinates for your footlocker in the appropriate lines that you got from the 'whereami' cheat.

You will likely have to test the script a couple of times to get the Footlocker's orientation correct, I suggest sticking to North or 0.00, East or 90.00, South or 180.00, and West or 270.00, but you can use any others.

Regarding the items you wish to place in the Footlocker, you can easily add more of the CreateItemOnObject lines... hundreds if you want to, all you have to do is change the item tags in the first set of quotations. The ones that look like the 'giveitem' cheat codes.

Also note the last CreateItemOnObject line in the script has a 2 on the end, this is if you wish a certain quantity of the same item to be placed into the container, so in this line when run it would place 2 of those saber crystals with the item tag of g_w_sbrcrstl04 in the locker, you can use any number, I have used up to 500 with no problems.

Save your script as... say ev_footlkr1.nss make sure you save it as an .nss file and not .txt.

Next you will have to compile it a good thread to help you with that is here. (http://www.lucasforums.com/showthread.php?t=143681)

Once you have your script compiled and you have your ev_footlkr1.ncs, you can move on to the last parts.

FYI you can delete the .ndb files that the compiler generates.

Next you will need the .dlg file from an in game cutscene. The best place for attaching placeable spawning scripts is the mandantory in game cutscenes. Example: the Sith and Republic Soldiers bantering on Manaan.
Open the module up and locate the cutscenes dialog (.dlg) file open it up in the dialogue editor of your choice, Fred's or tk102's and search for a line that is certain to be spoken, and you should see somewhere a place that says "script to run for this node" or "script that fires when spoken" and make sure it is blank, if it is then you can easily enter your script name in there, in your case it would be ev_footlkr1. Save the edited .dlg file.

Place the .dlg file you edited, the ev_footlkr1.ncs, the footlker099.utp, and all of your possible custom item files you want to place in the Footlocker into your override.

Fire up the game, and then load your save you have before entering that area or activating that dialogue, and see what happens, as I stated above you may have to test the orientation of your placeable a couple of times, but that is just a simple number change in the script and a recompile.

This is why I personally favor useing the Metal Box placeable as it's orientation doesn't really matter. ;)

Once you get the hang of it you will find this easy to do. :eyeraise: Wow... this is a mini-tutorial isn't it? :)

I hope this helps! :D
 tk102
01-27-2005, 11:08 AM
#2
When spawning an object of any kind, it is important to take re-entry into consideration. Most of the time, you only want to spawn something once, so you have to come up with a way of determining ahead of time whether you've already spawned something or not.

1. Check for the presence of the spawned object.

Seems pretty straightforward right? If the object exists, don't spawn another one. This method works well for placeables and spawned items that go into a spawned placeable.

An example of the code would look like this:

void main() {

object oContainer=GetObjectByTag("spawned_container_tag");
if (oContainer==OBJECT_INVALID) {
vector vContainer=Vector (0.0, 0.0, 0.0);
location lContainer=Location(vContainer, 0.0);
oContainer= CreateObject(OBJECT_TYPE_PLACEABLE, "container_template", lContainer);
CreateItemOnObject("item_template", oContainer);
}
}

2. Set a Local Boolean

This method is good for items that are being spawned into a pre-existing container. The idea is that we're going to put an invisible flag upon the container when we spawn the items for the first time. Then if our script fires again, it will first check for the existence of that flag and, if present, abort. If you firing your spawn script from a dialog, you could also use the presence of the boolean flag in a Conditional Script to prevent the dialog branch from being available.

Note: In general, it is best to write only to Local variables of objects, not creatures since they use them for walking waypoints and other AI. Unless you've researched the AI scripts and know which ones are safe to use, stick to object or use Global variables.
Example:


void main()
{
//Conditional Spawn NPC Script By TK102, Darth333, and RedHawke
int nBoolSlot=6; //any number 0-7 can be used here

object oLocker=GetObjectByTag("footlker099"); // get a reference to the pre-existing container

int nCheck=GetLocalBoolean(oLocker ,nBoolSlot);

if (nCheck) { return; } //exit if TRUE
CreateItemOnObject("g_w_lghtsbr05", oLocker);
CreateItemOnObject("g_a_mstrrobe01", oLocker);
CreateItemOnObject("g_w_sbrcrstl04", oLocker, 2);

// now close the door so we can't re-enter
SetLocalBoolean(oLocker,nBoolSlot,TRUE);
}


3. Set a Global Boolean

This method is suitable for creatures. Instead of writing a value locally to an object, we will write it to the memory of the game itself. To do this we will need to use a boolean variable that is defined in globalcat.2da. If you think you can find an obsolete Global Boolean that is already defined (like one from the Endar Spire) you can use that. Otherwise you'll have to edit globalcat.2da, add your new boolean, and put it in your override (and distribute it with your mod).

Example:


void main()
{
int nCreatureSpawned = GetGlobalBoolean("my_global_bool");
if (nCreatureSpawned) { return; } //exit if TRUE
CreateObject( OBJECT_TYPE_CREATURE, "creature_template", GetLocation(GetFirstPC()) );

// now close the door so we can't re-enter
SetGlobalBoolean("my_global_bool",TRUE);
}
 Darth333
07-12-2005, 9:05 AM
#3
Basic npc/placeable spawn scripts:

Placeable:

void main()
{
CreateObject(OBJECT_TYPE_PLACEABLE, "container_templateresref", Location(Vector(0.00,0.00,0.00), 0.0));
}


Creature:

void main()
{
CreateObject(OBJECT_TYPE_CREATURE, "creature_templateresref", Location(Vector(0.00,0.00,0.00), 0.0));
}

- container_templateresref and creature_templateresref correspond to the name of the *.utc or *.utp file for your creature/placeable.
-(0.00, 0.00, 0.00), 0.00 correspond respectively to the x y z coordinates and the orientation in degrees . For Kotor I, do a whereamI cheat to get them . For Kotor II, you will need the whereami armband available here: http://www.starwarsknights.com/tools.php)


How to add your items to an existing container that does not have a unique tag?

If there are other containers with the same tag in the game and don't want to end up adding your custom items in all the other ocntainers, you can use the GetNearestObjectToLocation function to specify a location and then target the nearest object to that location:

// 228: Get the nNth object nearest to lLocation that is of the specified type.
// - nObjectType: OBJECT_TYPE_*
// - lLocation
// - nNth
// * Return value on error: OBJECT_INVALID
object GetNearestObjectToLocation (int nObjectType, location lLocation, int nNth=1);

here is a sample script:
void main () {
//the coordinates can be obtained with the whereami armband (http://www.starwarsknights.com/tools.php).
//Just stand the closest as you can from the container you want to use..
vector vecCont;
vecCont.x = 0.0; // x coordinate goes here
vecCont.y = 0.0; // y coordinate goes here
vecCont.z = 0.0; // z coordinate goes here

int nIdx = 1;
location locCont = Location(vecCont, 0.0);
object oContainer = GetNearestObjectToLocation(OBJECT_TYPE_PLACEABLE, locCont, nIdx);

while (GetIsObjectValid(oContainer)) {
if (GetTag(oContainer) == "my_object_tag") {
CreateItemOnObject("item_template", oContainer);
CreateItemOnObject("item_template", oContainer);
break;
}
oContainer = GetNearestObjectToLocation(OBJECT_TYPE_PLACEABLE, locCont, ++nIdx);
}
}



How to spawn a container when I enter an area:

(you can always decompile the script and add the lines to spawn a container or you can use the easy following method which gives the same results at the end)

1. extract the On_enter script for the module. Check the .are file if you are unsure. Per example, when you enter the bar in NAr Shadaa, the script would be: a_306onenter.ncs
2. rename the script you just extracted to something else: exmaple old__a_306onenter.ncs
3. Create a new script:



void main()
{
object oEntering = GetEnteringObject();
object oPC=GetFirstPC();
if (GetIsPC(oEntering))
{
//check if the object is already there to avoid multiple objects
if (!GetIsObjectValid(GetObjectByTag("o")))
{
//replace the (0.00,0.00,0.00) by the xyz coordinates where you want to spawn the container.
//for TSL, use the whereami armband http://www.starwarsknights.com) to get the coordinates. For kotor use the whereami cheat
oContainer= CreateObject(OBJECT_TYPE_PLACEABLE, "container_templateresref", Location(Vector(0.00,0.00,0.00), 0.0));
}
// Fire the old onenter script that we renamed at step 2:
ExecuteScript("old_a_306onenter", OBJECT_SELF);
}

}


4. Save your script as a_306onenter.nss (the original name of the On enter script we extracted) and compile.

How to spawn a npc in an area:

It works exactly the same as a container:
1. extract the On_enter script for the module. Check the .are file if you are unsure. Per example, when you enter the bar in NAr Shadaa, the script would be: a_306onenter.ncs
2. rename the script you just extracted to something else: exmaple old__a_306onenter.ncs
3. Create a new script:


void main()
{
object oEntering = GetEnteringObject();
object oPC=GetFirstPC();
if (GetIsPC(oEntering))
{
//check if the object is already there to avoid multiple objects
if (!GetIsObjectValid(GetObjectByTag("o")))
{
//Note that the script uses OBJECT_TYPE_CREATURE instead of OBJECT_TYPE_PLACEABLE - that's the only difference with the container:
CreateObject(OBJECT_TYPE_CREATURE, "my_npc_templateresref", Location(Vector(43.41,-0.28,9.66), 0.0));

// this portion is optional and will only work if you spawn the npc not too far from where you enter the area - careful if there are scripted cutscenes too.
// You can also use the On perception event instead of the on enter script for this.
NoClicksFor(0.5);
//Make the NPC walk towards you:
AssignCommand((GetObjectByTag("my_npc_tag")),ActionMoveToObject(oPC));
//Make the npc initiate the converstation after approcahing you:
AssignCommand ((GetObjectByTag("my_npc_tag")), ActionDoCommand(ActionStartConversation(oPC)));
}

ExecuteScript("old_a_306onenter", OBJECT_SELF);
}

}


4. Save your script as a_306onenter.nss (the original name of the On enter script we extracted) and compile.

How to equip/unequip a npc with new stuff when entering an area:

Again, it's very similar to the above:
1. extract the On_enter script for the module. Check the .are file if you are unsure. Per example, when you enter the bar in NAr Shadaa, the script would be: a_306onenter.ncs
2. rename the script you just extracted to something else: exmaple old_a_306onenter.ncs
3. Create a new script:


void main ()
{
object oEntering = GetEnteringObject();
object oNPC = GetObjectByTag("my_npc_tag", 0); //identify the targetted npc
object oGun1 = GetItemInSlot(INVENTORY_SLOT_RIGHTWEAPON ,oNPC); // identify the weapon slot

if (GetIsPC(oEntering)){
object oNewgun = CreateItemOnObject("s_w_rptnblstr09",oNPC);//create the new object on the npc

if (GetIsObjectValid (oGun1)) //checks if the slot is empty or not
{
DestroyObject(oGun1);// if slot is not empty, then remove the previous object from inventory - this will destroy the previous object not just unequip it
}
AssignCommand (oNPC, ActionEquipItem(oNewgun, INVENTORY_SLOT_RIGHTWEAPON)); //equip the new object

ExecuteScript("old_a_306onenter", OBJECT_SELF); //run hte old OnEnter script
}
}


4. Save your script as a_306onenter.nss (the original name of the On enter script we extracted) and compile.

The other inventory slots are:
int INVENTORY_SLOT_HEAD = 0;
int INVENTORY_SLOT_BODY = 1;
int INVENTORY_SLOT_HANDS = 3;
int INVENTORY_SLOT_RIGHTWEAPON = 4;
int INVENTORY_SLOT_LEFTWEAPON = 5;
int INVENTORY_SLOT_LEFTARM = 7;
int INVENTORY_SLOT_RIGHTARM = 8;
int INVENTORY_SLOT_IMPLANT = 9;
int INVENTORY_SLOT_BELT = 10;
int INVENTORY_SLOT_CWEAPON_L = 14;
int INVENTORY_SLOT_CWEAPON_R = 15;
int INVENTORY_SLOT_CWEAPON_B = 16;
int INVENTORY_SLOT_CARMOUR = 17;
int INVENTORY_SLOT_RIGHTWEAPON2= 18;
int INVENTORY_SLOT_LEFTWEAPON2 = 19;
Page: 1 of 1