December 22, 2024, 06:37:13

Author Topic: Scripting Issues  (Read 103403 times)

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #100 on: May 28, 2010, 19:47:12 »
Quote
@Arparso: Why did you use the E.EnginesCount variable? Isn't it enough by using the E.engines list?

-- Just corrected myself: it's more efficient to check a variable that use walk trough a list... that's why you used enginesCount, right?
Exactly. SelectDevices() already returns the number of selected devices, so a call to AllNumOf() isn't required anymore. I wouldn't expect a performance difference between both variants, although it's hard to tell without knowing how these functions are implemented. Unless you're calling AllNumOf() a few thousand times per frame, you probably shouldn't even care.

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
(No subject)
« Reply #101 on: June 07, 2010, 14:54:51 »
Question:

How can I get the top speed of a ship on normal burn?

obj:tGetVelocity(); only reports the current speed (not helpfull as I know the speed at this point will be zero);
obj:tGetMaxVelocity(); gives the engines top possible speed when on full burn( again, not usefull as this speed exceeds the limit I'm trying to set).

The idea is to limit a formation leaders top speed slightly so that any other ship of the same class/type as the leader can take it's place in a formation instead of lagging behind.
Oh, and I can't look at the tacticstypes.ini for this info as the script is for any and all ships.
Better to look the fool by asking, then prove them right with ignorance.

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #102 on: June 07, 2010, 16:01:44 »
Quote
How can I get the top speed of a ship on normal burn?
I don't know of a script command or variable to directly get the normal speed, but it can be calculated. tGetMaxVelocity() gets you the highest achievable speed when routing additional energy into the engine subsystem. This is 50% more than the ship's regular speed, so the regular speed can be calculated by multiplying the maximum velocity with 2/3.

There's one caveat to that: probably every engine has both a setting for EnergyIn and EnergyOutput. The first dictates how much energy the engine uses each tick when being fully active (at regular speed) and the second setting specifies the amount of energy the engine itself generates each tick. If both values are equal, the engine can operate at regular speed (100%) without needing any additional energy and achieves up to 150% speed when being fed with support energy.
If EnergyOutput is actually higher than EnergyIn, the engine will actually exceed the regular speed without needing additional energy, but will still be limited to a maximum of 150% of the regular speed. Using the above calculation, however, gets you the regular speed, but not the actual speed the engine is really capable of.
The other way around is even worse: if EnergyOutput is lower than EnergyIn, the engine will not be able to reach the regular speed without any additional support energy. It also won't get to the usual 150% speed level, even if being fed enough support energy. tGetMaxVelocity() will NOT account for that (nor will the GUI) and will still report the theoretical 150% speed, even though the engine operates below that level. This leaves you with a calculated regular speed way above the actual engine's capabilities.

I don't know a good way to get around these two cases. Especially the second one is pretty bad as you'll calculate a speed way too fast for your engine while in the first case you'll just slow down your ship a bit, which alone would be tolerable. That being said, I'd consider it bad practice to actually include such an engine in your mod (with EnergyOutput being lower than EnergyIn), as it also screws up the manual speed panel on the GUI. Avoiding that, the simple calculation above should be sufficient for most needs.

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
(No subject)
« Reply #103 on: June 11, 2010, 15:26:12 »
Thanks Arparso, that works just fine.

Got another quick question that's making me go ggrrrr.

Using the 'Detected' rule, how do I find out which ship is doing the detecting?
Better to look the fool by asking, then prove them right with ignorance.

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #104 on: June 11, 2010, 18:08:05 »
Now that's a good question... I have absolutely no idea and I don't even see any helpful scripting command or variable.

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
(No subject)
« Reply #105 on: June 14, 2010, 15:07:31 »
Well, I managed to find an alternative route round this one, got a tick running every five seconds which issues a 'SelectShips' command with a few conditions. Not particularly neat, but it works (for the most part).

But now I've got another happy little question...

If a ship (or any item really) is in a list, is it possible to get that list ID from the ship/item?

So, for example, just say a single ship in a squadron has a cloaking device. Once the squadron has located an enemy, then the cloaked ship will engage its cloak for maximum advantage. Now while cloaked, this ship won't be able to follow the AI orders of the other ships so I'll need to pluck it out and place it in a 'squadron' of it's own. My problem is finding the squadron list ID to begin with.

EDIT 15/06/10:

Kind of got an answer. If' it's a ship and it's in a formation than the answer's yes (needs some carefull setting up first though).  Don't know about things not in a formation though.
Better to look the fool by asking, then prove them right with ignorance.

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #106 on: June 16, 2010, 23:38:40 »
Using IndexOf() it should be possible. You'd have to loop through all your squadron lists and look for your ship in one of them using the aforementioned IndexOf(). I wrote a short rule doing just that:

Code: [Select]
// description: looks through all lists with ids between E.firstList
// and E.lastList to find E.object and returns the list's id or -1
// param: E.firstList - id of the first list to look through
// param: E.lastList  - id of the last list to look through
// param: E.object    - the object being searched
RULE event GetFirstListContainingObject
:action
// stores the list currently being searched, starts with first list
E.currentList := E.firstList;
// marks, if the object has been found yet (currently 0, false)
E.foundObject := 0;

// loop through all lists, unless the object has been found
While(E.currentList <= E.lastList & E.foundObject = 0,
// look for the object in the current list
E.list := IndexOf(E.currentList, E.object);
// if object has been found, set foundObject to 1 (true)
If(E.list > -1,
E.foundObject := 1;
);
// advance to the next list
E.currentList := E.currentList + 1;
);

// check, if the object has actually been found in one of the lists
If(E.foundObject = 1,
// object has been found
// get the last list id and return it to the event caller
E.currentList := E.currentList - 1;
Debug("Object", E.object, "was found in list", E.currentList);
return(E.currentList);
,
// else return -1
Debug("Object not found in any list");
return(-1);
);
:end
END

Use it like so:

Code: [Select]
E.listId := LocalEvent(GetFirstListContainingObject,
E.firstList := 10;
E.lastList := 14;
E.object := m.ship)
);

There's one big problem regarding the scope of variables, though. Basically, every MACHINE has it's own lists. List 55 in one MACHINE can and probably will contain a totally different selection than list 55 in a different MACHINE. If the above rule for "GetFirstListContainingObject" is not in the same MACHINE as the place where you're calling it via LocalEvent(), it won't be able to access the correct lists and give wrong results. Sadly I don't know a way around this issue...

Also don't search through lists with the Id -1, because the above code returns -1 as error code, if it didn't find the object in any of the lists. If including the list -1 in the search, you couldn't differentiate between "not found" and "found in list -1" ;)

PS: While looking at the list of script commands Nexus offers, I realize I could have used InSelection() instead of IndexOf(), but it works either way.

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
(No subject)
« Reply #107 on: June 17, 2010, 00:46:19 »
Thanks Arparso, that's certainly opened up a new avenue or two.
Quick question, where did you get the 'E.FirstList' & 'E.LastList' parameters from? It's the first time I've seen those particular variables.

My solution went along these lines...

Code: [Select]
    E.Leader:=E.ship:FormLeader;
    Debug("Squadron leader is ",E.Leader);

E.Index:=IndexOf(M.LeadersList,E.Leader);
ThisSquadron:=GetN(M.SquadIndex,E.Index);
Debug("This Squadron is ",ThisSquadron);

M.NewList:=GetfreeSel();
SelectShips(M.NewList,InSelection(ThisSquadron,S.this));
ExecList(M.NewList,
Debug(ThisSquadron,"Squadron consists of ",S.this);
);

I should point out that during the filtering process, all available ships are placed in formations which are then catalogued (M.SquadIndex) with the formation leaders also being recorded  (M.LeadersList).  Although I believe this'll be sufficient for my needs (at least for now, lol), I daresay I'll integrate your approach at some point to handle any possible stationary objects.

Once again, thank you  :thumbup:
Better to look the fool by asking, then prove them right with ignorance.

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #108 on: June 17, 2010, 10:29:17 »
Quote
Quick question, where did you get the 'E.FirstList' & 'E.LastList' parameters from? It's the first time I've seen those particular variables.

Well, I just defined them on my own. As you know, you can raise a certain event using one of the following commands:These commands will execute all "reachable" (*) RULEs belonging to that particular event and supply them with a list of named parameters in var_set. Like so:
Code: [Select]
// no parameters:
LocalEvent(myEvent, 0);
// one parameter containing the number 1:
LocalEvent(myEvent, E.myParameter := 1);
// one parameter containing the value of another variable:
LocalEvent(myEvent, E.myShip := M.playerShip);
// multiple parameters combined:
LocalEvent(myEvent, E.myParameter := 1; E.myShip := M.playerShip; E.anotherParameter := P.count);
You can name these parameters as you wish, much like I named mine E.firstList, E.lastList and E.object. Predefined events such as FatalDamaged already come with a range of variables supplied by the game itself, but generally work just the same.

(*) what RULEs are "reachable" depends on the command itself and its location in the script. E.g. LocalEvent can reach each RULE in its own MACHINE and each embedded "child" MACHINE. Calling LocalEvent at the "root" SceneInit-RULE that every mission has, can reach ALL rules belonging to that event in the whole mission script, for example, because all of the mission's rulesets/MACHINEs are "children" of that root level. Calling LocalEvent() inside a MACHINE, however, won't execute any RULE outside that particular MACHINE (and its embedded child MACHINES, if it has any).

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #109 on: July 26, 2010, 22:58:43 »
Today I was working on a scripted "progress bar" for the repairing devices tab (critical for one mission, where you start with all your devices off-line (damage 100)). However, if you set the damage of a device to '100', you can't then set it to anything other than '0' (the variable will be changed, but nothing will appear on the gui until the bar reaches '0'.

The workarround to that problem I found was setting the damage to 99, but then the ship will start to automatically fix the devices, as it is supposed to, but completely screwing the "climax" of the mission.

So my question:
a) is there an other work-arround to my 1° problem?
b) if not, anyone know a way to stop the ship from fixing it's devices withouth altering the tacticstypes.ini?

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
(No subject)
« Reply #110 on: July 27, 2010, 01:14:28 »
As this is a scripted mission and you therefore know which object/s is/are to be damaged, could you not write a small routine that will select the various devices and then check their damage levels?

Then it could reset them where necessary and with the use of the 'Timer' command, you could re-run the routine as and when required (instead of using a 'tick').
Better to look the fool by asking, then prove them right with ignorance.

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #111 on: July 27, 2010, 01:58:05 »
The mission is like this, you start with all the devices disabled, so I put them with damage = 100, aka, completely destroyed, so the ship wouldn't try to fix it on it's own, and wrote a routine that would allow the player to cicle between all the devices that hasn't been fixed and choose which one they want to fix.
What I also wanted to do is write an other small routine (which I've already wrote, btw) that would "fake" a fixing progress bar for the duration of the fixing, and in doing that I encountered the problems I listed above.

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #112 on: August 31, 2010, 23:05:26 »
Just checking, though I know the answer... is there a way to make an event kick in when a weapon hits a target? like the ion-scream bomb, for example.

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #113 on: September 01, 2010, 01:02:34 »
Well, the FirstHit event kicks in if you've previously requested it for each ship using obj:tRequestFirstHitEvent() (and immediately request it again after each hit). You only get the victim and the attacker, though, not the specific weapon landing the hit. Can't think of anything else right now.

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #114 on: September 01, 2010, 01:24:29 »
Yeah, I know that one. But what put it off is the thought of an other weapon beating the one I requested to the target ship... Meh, I think that a mere delay will do it...

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #115 on: September 06, 2010, 00:53:56 »
About that previous issue, I managed to find a way to narrow down the problem.

Basically, when a specific weapon fires, a firstHit event is called regarding the targetted ship, and then I save the attacker and victim in 2 separate lists but with the same index, so when the FirstHit event is called, all I have to do is check that the "e.shooter" variable of that rule corresponds to the object present in the "attackers" list in the same index as the one of the victim. There's, however, a giagantic fault with that. Nexus doesn't admit repeated objects in their lists, so if, let's say, 2 ships attack the same one, the code will only get triggered for one of the hits.

So, is there a way to have repeated objects in a list??

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #116 on: September 06, 2010, 11:15:43 »
I believe there is, if you're using an array rather than a normal selection. Use "Dim()" to create an array of a given size a and use "GetN()" and "SetN()" to retrieve or set individual array elements at a given position in the array. Something like:

Code: [Select]
MyShip := GetSceneObj("MyShip");
MyArray := GetFreeSel();
Dim(MyArray, 200);
SetN(MyArray, 15, MyShip);
MyShipToo := GetN(MyArray, 15);

Can't test it right now as I'm not at home, but that should work. However, if I remember correctly, Nexus doesn't support lists, arrays or selections bigger than 256 elements... for whatever arbitrary reason.

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #117 on: September 06, 2010, 16:20:50 »
Yeah, that did it! thanks!

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
(No subject)
« Reply #118 on: October 11, 2010, 15:04:35 »
Hi All,

Quick question, does anyone know where to find the code that triggers the various warnings (I'm mainly interested in the one for detecting incoming fighters, but I'd like to see the rest too)?

Thanks.
Better to look the fool by asking, then prove them right with ignorance.

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #119 on: October 11, 2010, 20:29:37 »
I think those might be hardcoded. I'm not completely sure, of course, but I don't remember stumbling across any script code related to issuing those warnings.

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #120 on: December 01, 2010, 18:34:50 »
A question:

I've been making a cinematic scene that would show a couple hundred of ships appearing out of nowhere.
To be able to do that I've been turning them into wrecks the minute they appear, by changing their behaviour to 4. However, that didn't work, they still behave and more importantly, count as normal ships, so when I hit 20 or so the game crashes.
These ships appeared with the CreateShip command, they weren't part of the entities section.
My question:

How can I bypass this? any ideas?

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(no subject)
« Reply #121 on: December 02, 2010, 02:19:59 »
Tried it out and found a simple workaround: simply make the newly spawned ship disappear and immediately let it appear again. Of course, set behaviour to 4 before making the ship disappear or else you'll still run into the unit limit:

Code: [Select]
E.newShip := CreateShip(#styp_gtc_fenris, #race_player, "DynamicShip");
E.newShip:behaviour := 4;
E.disappearedShip := Disappear(E.newShip);
Appear(E.disappearedShip);

My interpretation of what happens internally:
  • spawning the ship with CreateShip() will make it count for the ship limit, because it starts with behaviour 0
  • setting behaviour to 4 makes it behave like an asteroid or wreck, but it still counts for the ship limit
  • it will not count anymore, if you remove it from the scene using Disappear() on it
  • upon returning to the scene with Appear(), it will still not count - because it enters the mission with behaviour 4 as an asteroid/wreck
  • ???
  • Profit!
Actually... I've got to thank you for that question, because experimenting with the solution I may have managed to work around the ship limit altogether :)
I made a separate thread for that, so that it won't get buried (and not found later) in this general purpose scripting thread.
« Last Edit: December 08, 2010, 12:07:50 by Arparso »