August 19, 2022, 23:18:38

Author Topic: Scripting Issues  (Read 72681 times)

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
Scripting Issues
« on: November 22, 2009, 09:59:33 »
Hi folks,

I've got a little bit of a sticky script that's been holding me up for a day or two.

What I'm trying to achieve is a script that will...

1) Install a device (well, a transport ship really, but the game sees it as a device) on a certain entity.
2) Send said device/transport model to a second entity.
3) When the device/transport gets close to the second entity, transfer and dock the device/transport.
4) Once docked, delete said device/transport to make room for others.

At the moment, I'm as far as docked. The debug code kicks to tell me that the transport has docked but I'm having trouble isolating the recently docked object from the rest.  At the moment, it'll either ignore the fact that they're docking or destroy everything within the area regardless of whether it's docked or not. Here's the code I've got for the 'sticky' bit...

Code: [Select]
If(E.location=M.CH_O,
TSD:=GetFreeSel();
SelectDevices(TSD,M.CH_O,Inset(S.this,25)&E.ship:docking=4);
ExecList(TSD,
Dump(TSD);
Debug("Deleting Station Transport");
DeleteDevice(S.this);
);
);

Anyone have an idea on how to resolve this little issue?

EDIT:

Blooming typical, I post for a solution to something that's been bothering me for days, then ten minutes later I find one. Life sure can be mean sometimes.

By adding a 'distance' section to the condition, I've got it to do what I wanted. But if anyone knows of a neater solution, I'm still all ears.
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 #1 on: November 23, 2009, 02:07:49 »
so... what was the solution?
anyway, I have an other problem, a lot simpler but it still bugs me like hell:

here's the deal. I've been working on a machine that will search for brusque changes in the shield integrity values of a ship, or otherwise, it'll keep a close watch if you manually disengage shields for some reason, it'll then store the previous value of the shield integrity (so far so good) and it will, supposedly, add it back to the shield via the M.Ship:=ShieldIntegrity:=*value*; command.
But there comes my problem, if i place the variable name in the *value* slot, the game will crash with a cExpression.cpp Line:521.
so... perhaps I'm doing somithing wrong there, I'm not too fluent with nexus variables...
anyway, here's the code:

Code: [Select]
RULE event Tick  //I start the tick line
:action
debug("tick1");
if(flag=1,  //this is a check so that the variable is not overwritten after the shield drain
set(shield,m.pship.5:ShieldIntegrity);
debug(shield);  //I declare and show the "shield" variable on the console
);
Delay(0,2.9,  //I set a 2.9 delay because the tick refreshes every 3 sec, and I want the less dead time possible.
set(shield2,m.pship.5:ShieldIntegrity);   //I declare the variable "shield2" as the value of the shield integrity 2.9 seconds after the first check
debug("tick2");
debug(shield2);
if(shield2=0,   //and here comes the magic: if the shield has been drained I perform this check
flag:=0;    //I disable the check
debug("drained and the shield value is:");
debug(shield);   //debuggind purposes
if(shield>1000,  //and here I compare the two values. if the previous value was higher than 1000, the if will take over. This is meant to avoid       triggers caused by "regular" shield draining.
debug("charged");
debug(shield);
m.pship.5:=shieldintegrity:=shield;  //}And in here I refil the ships' shield tank with the previous charge.
);
);
 ,0);

:end
END
tick 3



Damn.... there's got to be something magical about this site.... Old Dragon, same thing happened to me. The solution came no more than 10' after I finished typing this... the error was this:
m.pship.5:=shieldintegrity:=shield;  

it should have been:

m.pship.5:shieldintegrity:=shield;

now I have to figure out how to make this thing generic....

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #2 on: November 23, 2009, 09:06:24 »
That got to be the best help thread ever ... problems solving themselves - every tech support guy's wet dream ;)

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
(No subject)
« Reply #3 on: November 23, 2009, 09:14:53 »
Indeed there is... it's the magic of Arparso, lol. The very thought of posting it on the Skirmisher forum seems to make the problem roll over and play dead. lol

But more seriously, the solution code to my problem is...

Code: [Select]
If(E.location=M.CH_O,
TSD:=GetFreeSel();
SelectDevices(TSD,M.CH_O,Inset(S.this,25)&E.ship:docking=4&Distance(S.this,M.CH_O)<100);
ExecList(TSD,
DeleteDevice(S.this);
);
);

As for making yours more specific Mularac, hmmm...

You could try encapsulating the code within a 'SelectShips' command with the condition 'S.race=#race_Player&S.this:IsShielded', if you're only interested in the player or 'S.race=#race_Player|Not(S.race=#race_Player)&S.this:IsShielded' if you want to include all objects within the scene that have active shields, then 'ExecList' it.

With that done, you could then replace the 'M.PShip.5' with 'S.this' instead.

The only problem would be with the variable name... perhaps it could be overcome with by using the variable 'Shield:Name'? Not too sure 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 #4 on: November 23, 2009, 09:33:52 »
You could also store the last shield value directly at the object level like this:

Code: [Select]
TICK 1

RULE event Tick
:action
SelectEx(s.ship & s.isShielded,
s:this:lastShieldIntegrity:=s:this:shieldIntegrity;
Debug("saved shield for", s.this, "with", s:this:lastShieldIntegrity);
);
:end
END

If the shield is currently active, it stores the current shieldIntegrity in the lastShieldIntegrity variable for each object. If the shield is not active, the value won't be overridden.

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #5 on: November 23, 2009, 11:47:45 »
thanks guys, tomorrow afternoon I'm gonna get right into it :P
not today, though... got to prepare for a big exam tomorrow.

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #6 on: November 23, 2009, 14:35:33 »
Even easier solution with no need for a tick event:
Code: [Select]
   MACHINE "ShieldPreserve"

        STATE ShieldPreserve
               
            RULE event In
                :action
                    SelectEx(s.shield,
                        EnableActivateEvents(s.this, 1);
                        Debug("enabled 'activate' events for shield", s.this, "on", s.this:owner);
                    );
                :end
            END
           
            RULE event DeviceActivated
                :action
                    if(e.device:shield,
                        e.device:owner:ShieldIntegrity := e.device:owner:LastShieldIntegrity;                      
                        Debug("Activated shield,", E.device, "on", E.device:owner, "( restored last integrity", E.device:owner:LastShieldIntegrity, ")");
                    );
                :end
            END
           
            RULE event DeviceDeactivated
                :action
                    if(e.device:shield,
                        e.device:owner:LastShieldIntegrity := e.device:owner:ShieldIntegrity;
                        Debug("Deactivated shield", E.device, "on", E.device:owner, "with last integrity at", E.device:owner:LastShieldIntegrity);
                    );
                :end
            END

        END

    END
When the shield gets deactivated (manually, per mission script or ship behaviour), it saves the ship's last known shield integrity in an object variable called "LastShieldIntegrity". Upon activating the shield again, this old shield integrity simply gets restored again. The script won't work for ships and/or shields, that aren't present at the start of the mission, though. You have to call EnableActivateEvents manually for each shield device, that gets spawned during the course of the mission - or else the script will simply ignore these additional shields.

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
(No subject)
« Reply #7 on: November 23, 2009, 19:50:53 »
Could either,
a) A  'LongRangeArrived' rule to accomadate any later ships arriving by IP .
or
b) A 'DockOut' rule to cover those that get released from a mothership.

Be added to cover any late additions?

These rules could simply call for the 'In' rule to run again...
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 #8 on: November 23, 2009, 20:41:56 »
Sure, that'll work. I'm not sure about ships created using CreateShip(), though (like in my little Warfare mod experiment) - I don't think, that command triggers any events per default.

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #9 on: November 23, 2009, 23:44:28 »
Probably not, unless you assign a GetSceneObj to those ship.
and a question, wouldn't that overide a previous and general ShieldIntegrity command issued to the ships with a given value? (like the one on SG:WB)

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #10 on: November 24, 2009, 00:44:49 »
Quote from: Mularac
Probably not, unless you assign a GetSceneObj to those ship.
GetSceneObj doesn't really interfere with events - it's just a way to store an object reference in a variable, so you can use that object much more easily in your scripts without having to Select it every time. The problem simply is the game not triggering any event when you create a new ship using CreateShip, so the ShieldPreserve machine has no way of knowing about the arrival of the new ship.

Quote from: Mularac
and a question, wouldn't that overide a previous and general ShieldIntegrity command issued to the ships with a given value? (like the one on SG:WB)
I don't quite understand, what you mean. Basically this won't override anything else, but different scripts might conflict with each other on some rare occasions. For example you might have a script automatically activating all inactive shields and another script automatically deactivating all active shields... of course, it's a stupid example, but obviously both these scripts won't work as expected when they are run at the same time.

I'm not really familiar with the Stargate shield script... could you elaborate?

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #11 on: November 24, 2009, 01:08:08 »
it's real simple, here's the code (well... a part of it):

Code: [Select]
State chargeshields

Rule event in
name "shield up"
:action
Debug("shieldup");
SelectShips(shieldup, 1);
ExecList(shieldup, S.this:shieldIntegrity:=4500000;);
Delay(0,1,Disable("shield up"),0);
:end
END

Rule event Longrangearrived
:action
E.ship:shieldIntegrity:=4500000;
makefullyknown(e.ship);
:end
END

It basically charges the shields of a ship at the start of a fight or when the ship jumps in.

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #12 on: November 25, 2009, 00:18:18 »
you sonova... it actually worked! from where the hell did you get that knowledge of nexus scripting system?!

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #13 on: November 25, 2009, 00:57:46 »
Uhm... magic? :P

I guess me currently studying computer science might have something to do with that. But its mostly learning-by-doing while creating my first missions, the Skirmisher or investigating questions from the forum, etc.

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #14 on: November 25, 2009, 01:23:46 »
you're studying computer science... what are the odds... me too :P

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #15 on: December 04, 2009, 21:59:14 »
there's a bit of a problem there with your code, when I send the "EnableActivateEvents" command and the shields of a ship havent been rised, then the previous shieldintegrity value are overwritten when I actually rise them, as the game detects that since the shields haven't been rised the shield integrity is "0".

So far my only solution has been to had the game inmediately rise the shields, even though there is no ship in sight, but that's only temporary.

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
(No subject)
« Reply #16 on: December 04, 2009, 22:33:49 »
Another option then, maybe, is to manually write the initial value?
This would remove the need to temporarily raise the shields at the start of the mission...
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 #17 on: December 04, 2009, 23:52:55 »
the initial value?
there's such thing???

On another topic, how do you change the name of a ship when you insert it on a mission? I only get the name that appears on the .sobj file...

Offline Arparso

  • Administrator
  • Lieutenant
  • *****
  • Posts: 558
  • Karma: 14
  • I can see you...
    • View Profile
    • http://arparso.de/nexus
(No subject)
« Reply #18 on: December 05, 2009, 01:28:24 »
@Mularac:
You'll need to initialize the "LastShieldIntegrity" variable of each ship with a proper value, if you want to have the shields fully loaded after their first activation. Simply change the first rule of my example script above to:
Code: [Select]
           RULE event In
                :action
                    SelectEx(s.shield,
                        EnableActivateEvents(s.this, 1);
                        s.this:owner:LastShieldIntegrity:=100000;            // raise this value, if it's not sufficient for your shields
                        Debug("enabled 'activate' events for shield", s.this, "on", s.this:owner);
                    );
                :end
            END
After starting the mission, the shields won't be up at first, but they should be fully loaded after their first activation. (if not, raise the initial LastShieldIntegrity value even more)

Other question: how do you insert your ship into the mission? If by "CreateShip()" - this command takes the ship's name as 3rd parameter.

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #19 on: December 05, 2009, 02:37:46 »
thanks, that did it.

and, no, the ship came from a fleet, added via de addlocation command. (campaign scripting)
I've tried the  *** := uGet("ship_***");, and it worked, because I could use "***" instead of "ship_***" in plenty of other things, but in the mission I get "ship_***" instead of "***"
That is, if I can now get pass the "I crash withouth no apparent reason" thing. I hate it that when I change two things I get four erros that each cost me a couple of hours....

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
(No subject)
« Reply #20 on: December 05, 2009, 10:11:00 »
Welcome to campaign level scripting, if nexus doesn't find a file it needs, then it throws temper tantrums like a spoilt brat!

As for renaming ships, there is a 'rename' command...

Code: [Select]
RenameShip(ship, name);
It renames the ship.

or why not give the ship the name you wish in the .Sobj file? seems to work fine for me...
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 #21 on: December 05, 2009, 12:52:26 »
Yeah, Nexus error handling mechanic can be summed up by "OMG!!! CRASH!!!"... except when you're in the editor, which gives you pretty useful error messages most of the time. But even the most minor script error will crash the game, no matter how trivial it really is.

Regarding ship names: the most elegant solution would be to create a proper text file containing the proper name for your ship in all the languages you want to cater to. Nexus does it that way in universetextstextsfleets.ini. For example, the Stiletto of the vanilla campaign is named "ship_stiletto" in the .sobj-files - so it's corresponding entry in the fleets.ini file looks like this:
Code: [Select]
TEXT "ship_Stiletto"
0 "Stiletto" $$data "07/23/2004 15:06:45" "" 1
1 "Stiletto" $$data "08/18/2004 09:31:54" "" 1
2 "Stiletto" $$data "06/23/2004 16:44:35" "" 1
3 "Stiletto" $$data "07/23/2004 15:06:45" "" 1
5 "Stiletto" $$data "09/02/2004 16:00:38" "" 1
END
Each line in the text block corresponds to a different language, identified by the starting number (0 = English, 1 = German, 2 = Hungarian, 3 = French, 5 = Italian ... at least I think so). "Stiletto" would be the ship's name for each of these five languages, but you could totally translate each name to each language as you can do with every text entry (like dialogues, for example). You can forget about the $$data stuff and everything after it - probably just remainders of a proprietary tool Mithis used to manage all their text entries.

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #22 on: December 05, 2009, 13:15:41 »
oh... thanks, to the both of you. And no Old Dragon, I can't really do that, as I for example have the Angelwing sindrom on one of the ships, it'lll change during one of the missions... so assigning the same name to both ships doesn't seem to be the right thing to do...
And I get the error when I press start campaign, so where do you think the bugger is? episode_1.rules? tacticstypes.ini? some missing entry in one of the text files? (it's not the 1° mission, I've already tested that)

Nevermind, solved it...

Offline Mularac

  • Lieutenant
  • ***
  • Posts: 531
  • Karma: 11
    • View Profile
(No subject)
« Reply #23 on: December 10, 2009, 22:24:25 »
here's a quick one: how do you detect that a wrecked ship has been destroyed? (modification level scripting, not campaign)

Offline The Old Dragon

  • Ensign
  • ***
  • Posts: 362
  • Karma: 6
    • View Profile
    • http://
(No subject)
« Reply #24 on: December 10, 2009, 23:39:58 »
It might be a quick question, but I doubt the answer will be.

I've recently been playing around with wrecks myself (one of the N:TAA scenes is set in a ship graveyard). So far, I've been having problems with manipulating them in the normal ways (selectships,etc) because nexus only 'works' with live ships, though wrecks still count towards the scenes total objects! However, if you assign it a name in the normal way then you can use them in your scripts, it's just damn long-winded manually adding them to lists! But getting back to your question...

Assuming that this is an objective event that your working on (and therefore quite specific in what you're watching), what you could try...

1)  Is to assign the wreck a name.
2)  Using a 'tick' rule, maybe you could keep an eye on the wrecks damage level, something like...

                   
Code: [Select]
If(M.Wreck1:damage=0, localevent(Call something rule));
However, the tick could miss it and crash the scene  :(

3)  There may be a preset 'exploding' rule in the manual, perhaps you could use that with the wrecks name as a condition?

As I've not really needed to know when a wrecks gone nova, all I've got are some theories, but maybe it'll put you on the right path though.
Better to look the fool by asking, then prove them right with ignorance.