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.

"Advanced" Scripting Questions

Page: 1 of 1
 Exile007
02-12-2011, 8:12 PM
#1
Greetings Holowan!

I've been trying to do some scripting that seems a bit "advanced" for me.

What I'm trying to do is make a function for boss fights that allows me to return both the player and the boss to a waypoint called "wp_hq_pc" or "wp_hq_boss." Because I would like to make the source code appear more complicated than it actually is, and because I want to be able to reuse the function if it works as it would save time while scripting. I would also like to know a little bit more about how code works in general.

With that said, here is my function that I made.

void ReturnToHomeBase(object oCreature, string sTag) {

object oCreature;
location lHomeBase=GetLocation(GetObjectByTag("wp_hq_"+sTag));
AssignCommand(oCreature, JumpToLocation(lHomeBase));
}

Applied to the situation...


if (nParam == 0) {

ReturnToHomeBase(oPC, "pc");
ReturnToHomeBase(oBoss, "boss");
}
And yes, the PC and Boss have been defined earlier in the script. Unfortunately, neither the player nor the boss jump to the location. :(

I've also tried to create a function that spawns multiple creatures in the same position, but this one crashes the game when ran. *facepalm*

void SpawnMinions(int nAmount, location lWhereToSpawn) {
//This will allow me to control minions spawned, that way I won't
//have to trudge through code to change # from 5 to 3 :P
int nAmount;
int nID;
while (nID < nAmount) {
CreateObject(OBJECT_TYPE_CREATURE, "g_elite", lWhereToSpawn);
nID=nID++;
}
}
Applied to the rest of the script...

location lSP=Location(Vector(-39.97,16.36, -1.96679), 270.0);
SpawnMinions(5, lSP);


Knowing me, I've probably missed something critical. Both scripts compile fine, but the former doesn't work, and the latter crashes the game. :eek:

I would appreciate any insight or help. :)
 Qui-Gon Glenn
02-12-2011, 8:33 PM
#2
I do not understand what you have posted.

Snippets are not too helpful, please post the entire code.... It is very hard to see what you have going on here without seeing the "void main()" also. Confusing to the max actually.

In your function call "void SpawnMinions(int nAmount, location lWheretospawn)" you are passing in the variable nAmount, yet you are declaring it again inside of the script as well as giving it no value. Same for nID.... do not assume it starts at zero (seems like it should, but....), tell it to start at zero (or one, whatever your situation calls for) by declaring "int nID = 0". The problem I see lies with nID... where does it get its value?

Your void main() that calls these functions you have made I assume provides these values.... or there is your problem.
 Exile007
02-12-2011, 8:52 PM
#3
It's rather incomplete - but here it is anyway.

Looking at source code from Kotor 2 - it didn't declare its integers most of the time (this is for Kotor 2 by the way).

//prototypes, first time I've used these

void SpawnMinions(int nAmount, location lWhereToSpawn) {
//This will allow me to control minions spawned, that way I won't
//have to trudge through code to change # from 5 to 3 :P
int nAmount;
int nID;
while (nID < nAmount) {
CreateObject(OBJECT_TYPE_CREATURE, "g_elite", lWhereToSpawn);
nID=nID++;
}
}

void ReturnToHomeBase(object oCreature, string sTag) {

object oCreature;
location lHomeBase=GetLocation(GetObjectByTag("wp_hq_"+sTag));
AssignCommand(oCreature, JumpToLocation(lHomeBase));
}

void main() {

object oPC=GetFirstPC();
object oBoss=GetObjectByTag("tag_with_spoilers");
int nParam=GetScriptParameter(1);

if (nParam == 0) {

ReturnToHomeBase(oPC, "pc");
ReturnToHomeBase(oBoss, "boss");
}

if (nParam == 1) {

ChangeToStandardFaction(oBoss, 1);
object oDisc=GetObjectByTag("g_disc");
int nDiscInt=0;
while(GetIsObjectValid(oDisc)) {

ChangeToStandardFaction(oDisc, 1);
oDisc=GetObjectByTag("g_disc", ++nDiscInt);
}
}
if (nParam == 2) {

object oDoor=GetObjectByTag("door_1");
SetLocked(oDoor, 0);
AssignCommand(oDoor, ActionOpenDoor(oDoor));
}
if (nParam == 3) {

//Disciples created inside door

location lSP=Location(Vector(-39.97,16.36, -1.96679), 270.0);
SpawnMinions(5, lSP);
}

}

Apologies for providing sufficient information.

EDIT: So I did a bit of debugging - and I found that if I comment out the "CreateObject(OBJECT_TYPE_CREATURE, "g_elite", lWhereToSpawn);", then the game doesn't crash. So for some reason, that line of code pisses the engine off. Still not sure why. Anybody have an idea?
 bead-v
02-13-2011, 4:21 AM
#4
Try this.
//prototypes, first time I've used these

void SpawnMinions(int nAmount, location lWhereToSpawn){
//This will allow me to control minions spawned, that way I won't
//have to trudge through code to change # from 5 to 3 :P

int nID = 0;
while(nID < nAmount){
CreateObject(OBJECT_TYPE_CREATURE, "g_elite", lWhereToSpawn);
nID++; //<<this does the same thing
}
}

void ReturnToHomeBase(object oCreature, string sTag) {
location lHomeBase = GetLocation(GetObjectByTag("wp_hq_"+sTag));
AssignCommand(oCreature, ClearAllActions());
AssignCommand(oCreature, JumpToLocation(lHomeBase));
}

void main(){
object oPC = GetFirstPC();
object oBoss = GetObjectByTag("tag_with_spoilers");
int nParam = GetScriptParameter(1);

if(nParam == 0){
ReturnToHomeBase(oPC, "pc");
ReturnToHomeBase(oBoss, "boss");
}
if(nParam == 1){
ChangeToStandardFaction(oBoss, 1);
object oDisc = GetObjectByTag("g_disc");
int nDiscInt = 0;
while(GetIsObjectValid(oDisc)) {
ChangeToStandardFaction(oDisc, 1);
oDisc = GetObjectByTag("g_disc", nDiscInt++);
}
}
if(nParam == 2){
object oDoor = GetObjectByTag("door_1");
SetLocked(oDoor, 0);
AssignCommand(oDoor, ActionOpenDoor(oDoor));
}
if(nParam == 3){
//Disciples created inside door

location lSP = Location(Vector(-39.97, 16.36, -1.96679), 270.0);
SpawnMinions(5, lSP);
}
}
Also make sure that the waypoints are in the .git, that the .git is either in the override or in the .mod and it's the first time you're entering the module, and check whether the g_elite.utc is in your override/.mod.
 Qui-Gon Glenn
02-13-2011, 7:31 AM
#5
Seeing your entire code, and since this is an ADVANCED scripting zone, your multiple conditions by nParam's value is a place where a CASE/SWITCH would be appropriate, and save you a little coding.
 bead-v
02-13-2011, 7:42 AM
#6
Seeing your entire code, and since this is an ADVANCED scripting zone, your multiple conditions by nParam's value is a place where a CASE/SWITCH would be appropriate, and save you a little coding.
Not really, the way he did it is shorter.
 Exile007
02-13-2011, 11:40 AM
#7
Not really, the way he did it is shorter.

And whenever I use Case/Switch, TSL gets angry at me and crashes. :(

Thanks bead-v, that script worked like a charm. The problem was that "nID=nID++" made the script get stuck in the while loop. The game was trying to spawn so many creatures at once that it just gave up and crashed (I changed the Spawn line of code to sending a message to the PC on the feedback screen, very useful debugging tool, and there were literally hundreds of messages).

Thanks for the help guys. :)
 bead-v
02-13-2011, 5:14 PM
#8
Hmm, are you maybe forgetting the break;-s?

switch(iInteger){
case 0:
//CODE GOES HERE
break; //this is obligatory since if it's missing the engine will continue reading the code block, which means reading any subsequent cases.
case 1:
//CODE GOES HERE
break;
.
.
.
}
 Qui-Gon Glenn
02-13-2011, 5:41 PM
#9
@ bead-v: Hmmmm...... Ok.... ? How so? I am a little confused by that, as typing nParam == x each time is a little more typing. But then, in a switch you do have to add the break.... I guess it's 6 in one half-a-dozen the other.

Either way, glad you got it working Exile007
 Exile007
02-13-2011, 7:55 PM
#10
Hm... switch isn't crashing the game, but none of my commands are running. I'm not sure what's wrong with the script, comparing it to the source code of other scripts in TSL. Mine is pretty identical to the standard script, only exception being the actual commands ran inside the cases.

Below is the full script of a personal mod I've been working on/off since... 2008 that most likely will not be released to the public. Just a small restoration according to my personal tastes and ideas.

Take a look and tell me what's wrong please? :)


//a_dess_cut.nss
//prototypes, first time I've used these

void SpawnGenoDisciples(int nAmount, location lWhereToSpawn) {
//This will allow me to control Genos spawned, that way I won't
//have to trudge through code to change # from 5 to 3 :P
int nAmount;
int nID=0;
while (nID < nAmount) {
CreateObject(OBJECT_TYPE_CREATURE, "g_genoelite", lWhereToSpawn);
nID++;
}
}

void main() {

object oPC=GetFirstPC();
object oDessicus=GetObjectByTag("Dessicus");
int nParam=GetScriptParameter(1);

switch (nParam) {

case 0:

location lLoc=GetLocation(GetObjectByTag("wp_hq_dess"));
location lLoc2=GetLocation(GetObjectByTag("wp_hq_pc"));

AssignCommand(oPC, JumpToLocation(lLoc2));
AssignCommand(oDessicus, JumpToLocation(lLoc));

break;

case 1:
ChangeToStandardFaction(oDessicus, 1);
object oGeno=GetObjectByTag("g_genodisc");
int nID2=0;
while(GetIsObjectValid(oGeno)) {
ChangeToStandardFaction(oGeno, 1);
oGeno=GetObjectByTag("g_genodisc", ++nID2);
}
break;

case 2:

object oDoor=GetObjectByTag("PitDoor");
SetLocked(oDoor, 0);
AssignCommand(oDoor, ActionOpenDoor(oDoor));

break;

case 3:

//Genos run out of PitDoor

location lGenoSP=Location(Vector(-39.97,16.36, -1.96679), 270.0);
SpawnGenoDisciples(5, lGenoSP);

break;

case 4:

object oGenoElite=GetObjectByTag("g_genoelite");
int nGenoElite=0;
location lPC=GetLocation(oPC);
while(GetIsObjectValid(oGenoElite)) {

AssignCommand(oGenoElite, ActionForceMoveToLocation(lPC, TRUE));
oGenoElite=GetObjectByTag("g_genoelite", ++nGenoElite);
}
break;

case 5:
ChangeToStandardFaction(oDessicus, 1);
int nGenoInt2=0;
while(GetIsObjectValid(oGenoElite)) {

ChangeToStandardFaction(oGenoElite, 1);
oGenoElite=GetObjectByTag("g_genoelite", ++nGenoInt2);
}
break;

case 6:

effect efVisual=EffectVisualEffect(3003);

location lExplode1=GetLocation(oDessicus);
location lExplode2=GetLocation(oPC);
location lExplode3=GetLocation(GetObjectByTag("PitDoor"));
location lExplode4=GetLocation(GetObjectByTag("DoorRing"));

ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode1, 0.0);
DelayCommand(0.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode3, 0.0));
DelayCommand(1.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode4, 0.0));
DelayCommand(2.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode1, 0.0));
DelayCommand(3.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode3, 0.0));
DelayCommand(3.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode4, 0.0));
DelayCommand(4.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode1, 0.0));
DelayCommand(4.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode2, 0.0));
DelayCommand(5.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode2, 0.0));
DelayCommand(6.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode2, 0.0));

break;
}
}
 bead-v
02-14-2011, 1:06 AM
#11
Yep, I know what's wrong :D

You cannot define variables inside the switch, unless you put either that part of the code or the entire case inside { }. So:

switch (nParam) {

case 0:{

location lLoc=GetLocation(GetObjectByTag("wp_hq_dess"));
location lLoc2=GetLocation(GetObjectByTag("wp_hq_pc"));

AssignCommand(oPC, JumpToLocation(lLoc2));
AssignCommand(oDessicus, JumpToLocation(lLoc));
}
break;

case 1:{
ChangeToStandardFaction(oDessicus, 1);
object oGeno=GetObjectByTag("g_genodisc");
int nID2=0;
}
while(GetIsObjectValid(oGeno)) {
ChangeToStandardFaction(oGeno, 1);
oGeno=GetObjectByTag("g_genodisc", ++nID2);
}
break;

case 2:
{
object oDoor=GetObjectByTag("PitDoor");
}
SetLocked(oDoor, 0);
AssignCommand(oDoor, ActionOpenDoor(oDoor));

break;

case 3:{

//Genos run out of PitDoor

location lGenoSP=Location(Vector(-39.97,16.36, -1.96679), 270.0);
SpawnGenoDisciples(5, lGenoSP);

}
break;

case 4:{

object oGenoElite=GetObjectByTag("g_genoelite");
int nGenoElite=0;
location lPC=GetLocation(oPC);
while(GetIsObjectValid(oGenoElite)) {

AssignCommand(oGenoElite, ActionForceMoveToLocation(lPC, TRUE));
oGenoElite=GetObjectByTag("g_genoelite", ++nGenoElite);
}

}
break;

case 5:{
ChangeToStandardFaction(oDessicus, 1);
int nGenoInt2=0;
while(GetIsObjectValid(oGenoElite)) {

ChangeToStandardFaction(oGenoElite, 1);
oGenoElite=GetObjectByTag("g_genoelite", ++nGenoInt2);
}
}
break;

case 6:{

effect efVisual=EffectVisualEffect(3003);

location lExplode1=GetLocation(oDessicus);
location lExplode2=GetLocation(oPC);
location lExplode3=GetLocation(GetObjectByTag("PitDoor"));
location lExplode4=GetLocation(GetObjectByTag("DoorRing"));

ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode1, 0.0);
DelayCommand(0.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode3, 0.0));
DelayCommand(1.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode4, 0.0));
DelayCommand(2.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode1, 0.0));
DelayCommand(3.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode3, 0.0));
DelayCommand(3.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode4, 0.0));
DelayCommand(4.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode1, 0.0));
DelayCommand(4.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode2, 0.0));
DelayCommand(5.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode2, 0.0));
DelayCommand(6.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode2, 0.0));

}
break;
}

This should work.
 Exile007
02-14-2011, 1:17 AM
#12
I got a ton of compiler errors, I think it's because once a variable is defined in a pair of {}, it's only defined in that pair. I made this modification to it. It works. WOOT :D

//prototypes, first time I've used these

void SpawnGenoDisciples(int nAmount, location lWhereToSpawn) {
//This will allow me to control Genos spawned, that way I won't
//have to trudge through code to change # from 5 to 3 :P
int nAmount;
int nID=0;
while (nID < nAmount) {
CreateObject(OBJECT_TYPE_CREATURE, "g_genoelite", lWhereToSpawn);
ActionWait(1.0);
nID++;
}
}

void main() {

object oPC=GetFirstPC();
object oDessicus=GetObjectByTag("Dessicus");
int nParam=GetScriptParameter(1);

switch (nParam) {

case 0:{

location lLoc=GetLocation(GetObjectByTag("wp_hq_dess"));
location lLoc2=GetLocation(GetObjectByTag("wp_hq_pc"));

AssignCommand(oPC, JumpToLocation(lLoc2));
AssignCommand(oDessicus, JumpToLocation(lLoc));
}
break;

case 1:{
ChangeToStandardFaction(oDessicus, 1);
object oGeno=GetObjectByTag("g_genodisc");
int nID2=0;

while(GetIsObjectValid(oGeno)) {
ChangeToStandardFaction(oGeno, 1);
oGeno=GetObjectByTag("g_genodisc", ++nID2);
}
}
break;

case 2:
{
object oDoor=GetObjectByTag("PitDoor");

SetLocked(oDoor, 0);
AssignCommand(oDoor, ActionOpenDoor(oDoor));
}
break;

case 3:{

//Genos run out of PitDoor

location lGenoSP=Location(Vector(-39.97,16.36, -1.96679), 270.0);
SpawnGenoDisciples(5, lGenoSP);

}
break;

case 4:{

object oGenoElite=GetObjectByTag("g_genoelite");
int nGenoElite=0;
location lPC=GetLocation(oPC);
while(GetIsObjectValid(oGenoElite)) {

AssignCommand(oGenoElite, ActionForceMoveToLocation(lPC, TRUE));
oGenoElite=GetObjectByTag("g_genoelite", ++nGenoElite);
}

}
break;

case 5:{
object oGenoElite=GetObjectByTag("g_genoelite");
ChangeToStandardFaction(oDessicus, 1);
int nGenoInt2=0;
while(GetIsObjectValid(oGenoElite)) {

ChangeToStandardFaction(oGenoElite, 1);
oGenoElite=GetObjectByTag("g_genoelite", ++nGenoInt2);
}
}
break;

case 6:{

effect efVisual=EffectVisualEffect(3003);

location lExplode1=GetLocation(oDessicus);
location lExplode2=GetLocation(oPC);
location lExplode3=GetLocation(GetObjectByTag("PitDoor"));
location lExplode4=GetLocation(GetObjectByTag("DoorRing"));

ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode1, 0.0);
DelayCommand(0.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode3, 0.0));
DelayCommand(1.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode4, 0.0));
DelayCommand(2.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode1, 0.0));
DelayCommand(3.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode3, 0.0));
DelayCommand(3.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode4, 0.0));
DelayCommand(4.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode1, 0.0));
DelayCommand(4.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode2, 0.0));
DelayCommand(5.5, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode2, 0.0));
DelayCommand(6.0, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, efVisual, lExplode2, 0.0));

}
break;
}
}
 stoffe
02-14-2011, 11:40 AM
#13
void SpawnGenoDisciples(int nAmount, location lWhereToSpawn) {
//This will allow me to control Genos spawned, that way I won't
//have to trudge through code to change # from 5 to 3 :P
int nAmount;
int nID=0;
while (nID < nAmount) {
CreateObject(OBJECT_TYPE_CREATURE, "g_genoelite", lWhereToSpawn);
ActionWait(1.0);
nID++;
}
}


You're declaring a local variable nAmount inside the function which has the same name as the first function parameter. If that actually works it's just because the compiler is kind enough to overlook it since you're not assigning anything to that variable. :raise:

You shouldn't declare variables with the same name as function parameters though.
 Exile007
02-14-2011, 12:15 PM
#14
You're declaring a local variable nAmount inside the function which has the same name as the first function parameter. If that actually works it's just because the compiler is kind enough to overlook it since you're not assigning anything to that variable. :raise:

You shouldn't declare variables with the same name as function parameters though.

Hm... I'm still pretty much a n00b at scripting. So I shouldn't use the same variable name as I used in the parameters for the function? To me, my way made sense, because I thought I was referencing the same variable, and making it easier for the game to understand. So I should change either nAmount in the first parameter to another name, or the second nAmount to another name?

Gah, so confusing. *facepalm*
 bead-v
02-14-2011, 1:34 PM
#15
No, no; no renaming of nAmount.. when you type 'int nAmount' into the parameter you basically already define it. By defining another nAmount inside, you kind of overwrote the first one. And since the new one didn't have a value assigned to it, the while loop became endless (at least that's what I think caused the crash).

Anyways, when you define new functions, the variables that are defined as parameters of the function can be used inside the function without any further defining. If you define them again you overwrite the values you set when you call the function (Again, that's what I think happened).
 Exile007
02-15-2011, 1:17 AM
#16
All right, thanks for the help guys. I appreciate the tolerance of a scripting noob such as myself. :p
Page: 1 of 1