Page 100 of 118
Re: Scripters cove
Posted: Fri Jan 29, 2021 10:57 pm
by Redspear
OK so I'm almost certainly doing something stupid but here's the plan...
Upon ejecting, the player finds the replacement ship has several damaged pieces of equipment (assuming they were present on the original ship).
So, I need to:
- activate the script once the player ejects
- test for presence of undamaged equipment items that I wish to be affected
- change condition of those items to damaged
I've attempted as much like so:
Code: Select all
this.shipLaunchedEscapePod = function()
{
if (player.ship.equipmentStatus("EQ_ECM") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_ECM") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_FUEL_SCOOPS") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_FUEL_SCOOPS") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_ENERGY_UNIT") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_ENERGY_UNIT") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_DOCK_COMP") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_DOCK_COMP") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_GAL_DRIVE") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_GAL_DRIVE") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_SCANNER_SHOW_MISSILE_TARGET") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_SCANNER_SHOW_MISSILE_TARGET") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_MULTI_TARGET") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_MULTI_TARGET") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_ADVANCED_COMPASS") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_ADVANCED_COMPASS") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_ADVANCED_NAVIGATIONAL_ARRAY") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_ADVANCED_NAVIGATIONAL_ARRAY") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_TARGET_MEMORY") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_TARGET_MEMORY") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_INTEGRATED_TARGETING_SYSTEM") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_INTEGRATED_TARGETING_SYSTEM") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_SHIELD_BOOSTER") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_SHIELD_BOOSTER") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_NAVAL_SHIELD_BOOSTER") = "EQUIPMENT_DAMAGED";}
if (player.ship.equipmentStatus("EQ_WORMHOLE_SCANNER") == "EQUIPMENT_OK")
{player.ship.setEquipmentStatus("EQ_WORMHOLE_SCANNER") = "EQUIPMENT_DAMAGED";}
}
No error reports but also no apparent effect.
Same (lack of) result using
escapePodSequenceOver.
Can anyone please tell me where I'm going wrong?
Re: Scripters cove
Posted: Fri Jan 29, 2021 11:57 pm
by stranger
Techically you have no ship with ECM etc between ejecting escape pod and arrival to station. You need set equipment state after having new ship.
Try this approach like in my Hard Eject:
Code: Select all
this.shipLaunchedEscapePod = function()
{
this.$escapeFlag = 1; // eject recorded
}
this.shipDockedWithStation = function()
{
if (this.$escapeFlag == 1) // eject detected
{
// your code here
this.$escapeFlag = 0; // don't forget to reset escape flag!
}
}
Re: Scripters cove
Posted: Sat Jan 30, 2021 12:14 am
by montana05
Maybe not what you are looking for but player.ship.takeInternalDamage();
is (randomly) damaging equipment as well.
Re: Scripters cove
Posted: Sat Jan 30, 2021 12:52 am
by Redspear
montana05 wrote: ↑Sat Jan 30, 2021 12:14 am
Maybe not what you are looking for but player.ship.takeInternalDamage();
is (randomly) damaging equipment as well.
Thanks but I think I might have solved it... (totally would have tried that 5 minutes ago
)
stranger wrote: ↑Fri Jan 29, 2021 11:57 pm
Techically you have no ship with ECM etc between ejecting escape pod and arrival to station. You need set equipment state after having new ship.
Try this approach like in my Hard Eject:
That was indeed part of the problem (although I would have thought that using
escapePodSequenceOver would have prevented that being an issue) and resulted in error reports activating (at least the script was actually running!), so thanks for putting me on the right track.
Turns out that
Code: Select all
player.ship.setEquipmentStatus("EQ_ECM") = "EQUIPMENT_DAMAGED";
is bad form.
It should be
Code: Select all
player.ship.setEquipmentStatus("EQ_ECM", "EQUIPMENT_DAMAGED");
which worked a treat.
Thanks both
Re: Scripters cove
Posted: Tue Feb 16, 2021 2:46 pm
by tsoj
A quick question: On the wiki
there is an example on how to use
station.shipyard
:
Code: Select all
var ship_count = system.mainStation.shipyard.count;
I found that
.count
is undefined but
.length
works. Should I edit the wiki or am I missing something?
Re: Scripters cove
Posted: Tue Feb 16, 2021 8:49 pm
by phkb
tsoj wrote: ↑Tue Feb 16, 2021 2:46 pm
I found that .count is undefined but .length works. Should I edit the wiki or am I missing something?
Yep, looks like an oversight on my part. Please update the wiki when you get a chance.
Re: Scripters cove
Posted: Wed Feb 17, 2021 11:36 pm
by tsoj
I had the idea to write and OXP that balances the ship price based on its properties (something close to
this). I've run into a small and a big issue.
The small issue is that when I get a ship from the
shipyard I only get the shipdata.plist info about the ship. Because I need the mass of a ship I temporarily create a ship with
ship = system.addShips("["+shipdataKey+"]", 1, Vector3D(100000000, 0, 0))[0];
and then delete it afterwards
ship.remove(true);
.
This seems pretty inelegant, I couldn't think of a better solution though, but maybe someone else can.
The bigger issue where I haven't found a workaround yet is, that I need to change the price of the player-ship. I've only found the javascript read-only variable
price, but I took a peak at the source code, and it doesn't seem like there is a trivial solution.
Maybe having a callback that gets called when the
tradeInValue
function gets executed so that one can give an alternative calculation of the tradeInValue that replaces the default calculation? Is something like this even possible?
I couldn't think of any workaround that comes without big issues. For example, re-awarding credits or taking credits away after a ship purchase, could cause a negative credit score or that I couldn't buy a ship, even though my adjusted trade-in value is enough.
Re: Scripters cove
Posted: Thu Feb 18, 2021 12:53 am
by montana05
You can get the mass with ship.mass
for the prices I can suggest removeShipFromShipyard
and addShipToShipyard
, I never tried o modify the price of a ship with that but it might be worth a look.
Re: Scripters cove
Posted: Thu Feb 18, 2021 1:47 am
by tsoj
montana05 wrote: ↑Thu Feb 18, 2021 12:53 am
You can get the mass with ship.mass
for the prices I can suggest removeShipFromShipyard
and addShipToShipyard
Yes, that is actually my plan
. It seems to work, if I buy a ship from the shipyard I have to pay the adjusted price. Now, additionally to the already mentioned problems I found another issue:
ship.canAwardEquipment returns often true, even though in the shipyard it says that it can't be added to the ship. Is the equipment list in shipyard.plist only applicable to the player-ship?
Anyway, if anybody dares to look at some questionable JavaScript code:
https://gitlab.com/tsoj/oolite_balancedshipprices (very much still WIP)
Re: Scripters cove
Posted: Thu Feb 18, 2021 2:12 am
by montana05
tsoj wrote: ↑Thu Feb 18, 2021 1:47 am
I found another issue:
ship.canAwardEquipment returns often true, even though in the shipyard it says that it can't be added to the ship. Is the equipment list in shipyard.plist only applicable to the player-ship?
Not sure about that, a first wild guess would be that there might be a condition-script attached to the equipment.
Re: Scripters cove
Posted: Thu Feb 18, 2021 2:45 am
by phkb
tsoj wrote: ↑Thu Feb 18, 2021 1:47 am
Is the equipment list in shipyard.plist only applicable to the player-ship?
Given that the shipyard file defines ships that can be purchased by the player, yes, it's only applicable to player ships. You theoretically can't have a player ship without a shipyard.plist entry.
Re: Scripters cove
Posted: Thu Feb 18, 2021 2:49 am
by phkb
tsoj wrote: ↑Thu Feb 18, 2021 1:47 am
Anyway, if anybody dares to look at some questionable JavaScript code
I found that with player ship definitions, at least for core equipment, it's better to try something like this:
Code: Select all
var myShipDef = Ship.shipDataForKey("ship_data_key");
var equipKey = "EQ_FUEL_SCOOPS";
var found = "N/A";
if (!myShipDef._oo_shipyard) found = "Data error - no shipyard entry found on ship definition";
if (found === "N/A" && myShipDef._oo_shipyard.standard_equipment.extras && myShipDef._oo_shipyard.standard_equipment.extras.indexOf(equipKey) >= 0) found = "Standard";
if (found === "N/A" && myShipDef._oo_shipyard.optional_equipment && myShipDef._oo_shipyard.optional_equipment.indexOf(equipKey) >= 0) found = "Optional";
That avoids the need to actually create a ship of that type just so you can try the
ship.canAwardEquipment
function.
Re: Scripters cove
Posted: Thu Feb 18, 2021 5:20 pm
by tsoj
EDIT: I created a git pull request
---------------------------------------
What would you think about a function like
Ship.shipDataForKey but like this:
function setShipDataForKey(datakey : String, newShipData : Object)
?
Unfortunately I didn't manage to compile Oolite on my machine and I also don't really know Obj-C, but I thought about these changes in the code:
Adding to
OOShipRegistry.m (and to the respective header file):
Code: Select all
- (void) setShipInfoForKey:(NSString *)key with:(NSDictionary *)newShipData
{
[_shipData release];
_shipData = OODeepCopy(newShipData);
/* EDIT: ^this would be a bug, I meant to only change the shipData for a specific key.
But I'm not sure how to do it, does "objectForKey" return a pointer to
the NSDisctionary in _shipData or to a copy? if it returns a pointer to the original data, maybe we could do
it like this:*/
[[_shipData objectForKey:key] release];
[_shipData objectForKey:key] = OODeepCopy(newShipData);
}
----------------------------------------------------
And in
OOJSShip.m
:
Add this
Code: Select all
static JSBool ShipStaticSetShipDataForKey(JSContext *context, uintN argc, jsval *vp);
here
----------------------------------------------------
Add this
Code: Select all
{ "setShipDataForKey", ShipStaticSetShipDataForKey, 2 },
here
-----------------------------------------------------
And add this at the bottom of the file:
Code: Select all
static JSBool ShipStaticSetShipDataForKey(JSContext *context, uintN argc, jsval *vp)
{
OOJS_NATIVE_ENTER(context);
OOShipRegistry *registry = [OOShipRegistry sharedRegistry];
if (argc >= 2)
{
NSString *key = OOStringFromJSValue(context, OOJS_ARGV[0]);
NSDictionary *newShipData = OOJSNativeObjectFromJSObject(context, JSVAL_TO_OBJECT(OOJS_ARGV[1]));
[registry setShipInfoForKey:key with:newShipData]
OOJS_RETURN_BOOL(YES);
}
else
{
OOJSReportBadArguments(context, @"Ship", @"setShipInfoForKey", MIN(argc, 2U), OOJS_ARGV, nil, @"ship role");
return NO;
}
OOJS_NATIVE_EXIT
}
Re: Scripters cove
Posted: Sun Mar 21, 2021 11:45 am
by Phasted
Say, here's a brain-tickler: My world-script needs to create a timer on a ship (station) script... Do I leave the this
parameter as-is, referring to the world-script or should I change it to station.script
?
Re: Scripters cove
Posted: Mon Mar 22, 2021 9:14 pm
by phkb
If the script that is starting the timer runs through a worldScript function, and you are happy with there only being one timer in play,
this
is fine.
For example:
Code: Select all
this.startUpComplete = function() {
// in this instance "this" refers to the current worldScript
this._myTimer = new Timer(this, this.$myTimerFunction, 1, 1);
}
this.$myTimerFunction = function $myTimerFunction() {
// ...do stuff...
}
If, however, you want a separate timer per station, you can still refer to
this
, but you would have to add your scripts to the ship script of the station.
For example, to :
Code: Select all
this.startUpComplete = function() {
// find the station you want to attach your script to
var stations = system.stations;
for (var i = 0; i < stations.length; i++) {
if (stations[i].{property} == {value} { // you'd put in whatever criteria here that would allow you to identify the correct station.
// found it!
stations[i].script.$myTimerFunction = this.$myTimerFunction;
stations[i].script.$myTimerStarter = this.$myTimerStarter;
stations[i].script.$myTimerStarter();
}
}
}
this.$myTimerStarter = function $myTimerStarter() {
// in this instance, "this" refers to the stations ship script
this._myTimer = new Timer(this, this.$myTimerFunction, 1, 1);
}
this.$myTimerFunction = function $myTimerFunction() {
// ...do stuff...
}