Join us at the Oolite Anniversary Party -- London, 7th July 2024, 1pm
More details in this thread.

Scripters cove

Discussion and information relevant to creating special missions, new ships, skins etc.

Moderators: winston, another_commander

Fritz
---- E L I T E ----
---- E L I T E ----
Posts: 591
Joined: Sun Jul 12, 2015 2:30 pm
Location: Bavaria, Germany
Contact:

Re: Scripters cove

Post by Fritz »

Svengali wrote:
And as sidenote: Injection (or monkey-patching) is dangerous. In the end every AddOn developer looses the capability to control his own content and runtime behaviours of his/her own scripts. And clashes caused by this kind of thing are nearly impossible to spot.
What's even worse is that some things depend on the order of installation! If Spicy hermits is installed first, I could spot and "reproduce" it, but if not, it would simply override my script. And this would be a relatively simple case; in theory, there could be more than two OXPs involved!
Choose a cleaner approach whenever you can.
That's what I'm trying to do: Change as little as possible and keep the code simple!
"You wouldn't kill me just for a few credits, would you?" – "No, I'll do it just for the fun!"
User avatar
spara
---- E L I T E ----
---- E L I T E ----
Posts: 2676
Joined: Wed Aug 15, 2012 4:19 am
Location: Finland

Re: Scripters cove

Post by spara »

You could check the hermits with system.entitiesWithScanClass when the player leaves the system and compare the positions with your beacons. Should not be too complicated.

If you don't want to destroy the beacon with the hermit, why do you need to track the death of the hermit? Do you mean to remove the beacon on system exit?
Fritz
---- E L I T E ----
---- E L I T E ----
Posts: 591
Joined: Sun Jul 12, 2015 2:30 pm
Location: Bavaria, Germany
Contact:

Re: Scripters cove

Post by Fritz »

On system entry, I'll have to put beacons to all hermits stored in the player's database. When I do this, I'll additionally have to remove destroyed hermits. The beacon will remain though, because the "hermit memory" can't know that the hermit has been destroyed (In fiction, it's not a real beacon, because hermits don't have them, and the computer just stores the position, and calculates the orbit etc. in relation to other objects and beacons). I'll store the day of destruction, and after some time, the hermit will be rebuilt, at least if Spicy Hermit's isn't installed.

As I have mentioned in the Spicy Hermits thread, it would be possible to add boulders and other debris, perhaps even "construction ships", during the rebuilding time. But, sadly, it isn't worth to put too much effort into it, because destroyed hermits are very rare during normal playing. I've never destroyed one, and I've only once seen one being destroyed by NPCs.
"You wouldn't kill me just for a few credits, would you?" – "No, I'll do it just for the fun!"
User avatar
spara
---- E L I T E ----
---- E L I T E ----
Posts: 2676
Joined: Wed Aug 15, 2012 4:19 am
Location: Finland

Re: Scripters cove

Post by spara »

Fritz wrote:
I'll store the day of destruction, and after some time, the hermit will be rebuilt, at least if Spicy Hermit's isn't installed.
So you're creating something like [wiki]Station Validator[/wiki]?

Still sounds like something that could be handled in system.playerWillEnterSystem and system.playerWillExitSystem by cataloging hermits using system.entitiesWithScanClass and doing what ever you want to do with them. But maybe it's something different you have in mind :) .
Fritz
---- E L I T E ----
---- E L I T E ----
Posts: 591
Joined: Sun Jul 12, 2015 2:30 pm
Location: Bavaria, Germany
Contact:

Re: Scripters cove

Post by Fritz »

Not so complicated! As I said, destruction will be very rare for rock hermits, so all the effort in creating rebuilding phases, models (e.g. an asteroid with a smaller hole!) etc. would be wasted. I' only want to prevent destroyed hermits magically reappearing, because I'm certain that every player installing the OXP would try it! And because I'll have to store the positions anyhow, it won't be much additional work.
"You wouldn't kill me just for a few credits, would you?" – "No, I'll do it just for the fun!"
User avatar
spara
---- E L I T E ----
---- E L I T E ----
Posts: 2676
Joined: Wed Aug 15, 2012 4:19 am
Location: Finland

Re: Scripters cove

Post by spara »

Ok, I see. Sorry for being a bit slow sometimes :) . You want to create a beacon system _and_ a delayed rebuild.

I made the relocator instead of delayed rebuild for two reasons. First one being compatibility. Core tries to make sure that there is at least one hermit in all systems. It's for the core roles. There are fallbacks in case no hermit is found, but anyway. The second being simplicity in conjunction with the fact, that the player should not really know that the hermit is relocated. The knowledge spoils the illusion. If the player does not know it, then he/she assumes the hermit is gone and he/she has just found a new one.
Fritz wrote:
As I said, destruction will be very rare for rock hermits...
Now that depends totally on the player. I'm fairly sure there aremany Ooniverses out there where hermits get destructed all the time.

Good luck with your project :D .
Fritz
---- E L I T E ----
---- E L I T E ----
Posts: 591
Joined: Sun Jul 12, 2015 2:30 pm
Location: Bavaria, Germany
Contact:

Re: Scripters cove

Post by Fritz »

Yes, I want to have both. First the destruction thing should have been phase 2 of my hermit beacon OXP. But I wanted to have the data structure prepared for this from the beginning, so that updating won't be a problem, and that's why I started to think about it already. With using the visual effect beacon (this is working already) the delaying reappearance shouldn't be much additional work, so I'll try to include it into the first version. Of course I'll have to consider moved hermits too - in this case I won't have to recreate the destroyed one. For the player, it will be a new hermit, even if he uses my beacon OXP. I could additionally create a new hermit at the old position, but that's optional, I don't know if I'll do it.
Core tries to make sure that there is at least one hermit in all systems.
Even without OXPs, the player can find himself within a system without hermits, if he destroys them. It is entirely his fault if he chooses to do so! So not recreating them during his next visit to a system won't change anything significantly.
The second being simplicity in conjunction with the fact, that the player should not really know that the hermit is relocated. The knowledge spoils the illusion. If the player does not know it, then he/she assumes the hermit is gone and he/she has just found a new one.
Then I hope that no player will read our discussions! :lol:
"You wouldn't kill me just for a few credits, would you?" – "No, I'll do it just for the fun!"
User avatar
spara
---- E L I T E ----
---- E L I T E ----
Posts: 2676
Joined: Wed Aug 15, 2012 4:19 am
Location: Finland

Re: Scripters cove

Post by spara »

Fritz wrote:
Then I hope that no player will read our discussions! :lol:
Some might read them, but there's probably a big majority out there that does not follow the discussions regularly. And when the oxp is finished and bugs squished, the thread will fall out of sight.

I have one explanation though, if needed. In case hermits get destructed, the core spawns them back to their original places on system entry. An in-game explanation would be that they are built back. My oxp only changes the place they are built. :mrgreen:
ocz
Deadly
Deadly
Posts: 175
Joined: Tue Nov 10, 2015 1:59 pm

Re: Scripters cove

Post by ocz »

How is the distance to a star defined, when the fuel scoops kickin to harvest witch fuel? (star size * distance constant? And if yes, what are the values?)

Edit:
Nevermind. I looked into it myself and found:
(Distance: sun <-> player.ship) / sun's radius ≈ 1.155
[color=#000080]system.sun.position.distanceTo(player.ship.position)/system.sun.radius[/color] ≈ 1.155
Around this distance-radius relation the fuel scoops start collecting witchfuel. At least at the suns of the planets Quator, Ra and Relaes it has been this way.

Edit2: To be even more specific: sqrtroot(4/3) [(4/3)^(1/2) ≈ 1.155] * sun's radius is the distance from the sun's core (position) in which the fuel scoops start to harvest witchfuel
ocz
Deadly
Deadly
Posts: 175
Joined: Tue Nov 10, 2015 1:59 pm

Re: Scripters cove

Post by ocz »

Yet again a noobish question, but I really want to make sure, I don't litter timers everywhere.

I'm writing an AI (priorityAI) this time and implemented a timer for repeated condition checking. Of course I could have used the priority list itself with timed reconsiderations, but as the method it repeats is more like a function of the ship (it's a simulated Torusdrive) than a decision the ship takes, I wanted to keep them independent from each other to a certain degree.

Here's what I've got:

Code: Select all

this.name = "Solar Harvester AI";

this.aiStarted = function() {
	
	var ai = new worldScripts["oolite-libPriorityAI"].PriorityAIController(this.ship);
	ai.setCommunicationsRole("scavenger");

	ai.setParameter("_solarHarvesterReturnHome", false);	
	
[...] // Methods implemented for the AI.
	
	ai._solarHarvesterTorusDrive = function() {
->	 var timer = this.ship._solarHarvesterTorusSpeedTimer;
		if (this.ship.checkScanner().length !== 0 ||
		  this.ship.position.distanceTo(system.sun.position) < system.sun.radius * 1.48) {
			if (timer.isRunning) this.ship.velocity = this.ship.heading.multiply(this.ship.maxSpeed);
			// Drop out of Torus Speed to maxSpeed. Deceleration to set
			// speed happens naturally afterwards.
			timer.stop();
		}
		else this.ship.velocity = this.ship.heading.multiply(this.ship.maxSpeed * 32);
		// Accelerate to or refresh Torus Speed (32*maxSpeed).
		if (!this.ship && timer.isRunning) timer.stop(); //<- Will this do anything?
	}
	
	// Engage Torusdrive, check every 0.25 sec if there is something masslocking (excluding
	// Planets/Suns, including asteroids/loot) and stop or maintain Torus Speed (refresh velocity).
-> this.ship._solarHarvesterTorusSpeedTimer = new Timer(ai, ai._solarHarvesterTorusDrive ,-1 ,0.25); 
	
[...] // More AI methods.

	ai.setPriorities([
		
		[...] //Fighting, Fleeing and doing other stuff

		// Go to sun
		{
			condition: !ai._solarHarvesterConditionReadyToHarvest,
			behaviour: function () {
					ai._solarHarvesterBehaviourGotoHarvestOrbitAboveSun();
->				 this.ship._solarHarvesterTorusSpeedTimer.start();
				},
			reconsider: 20
		} 
		
	].concat(ai.templateWitchspaceJumpAnywhere()));
}
	
Please take notice, how implemented the timer as a property of the ship-object (this.ship._solarHarvesterTorusSpeedTimer), to make it itself referable and controllable for the method it repeats. The timer itself is bound to the AI object variable (ai in new Timer(ai, ai._solarHarvesterTorusDrive ,-1 ,0.25);)

To my knowledge (wiki) the timer should be removed when the ship is destroyed/docks/jumps out, as for once ai should be removed and then the object this.ship is also deleted.

But woe me, I found contradicting evidence.

Maybe this in itself was the mistake, but to check the timer I referred to it in the debug console by this.hTimer = this.harvester._solarHarvesterTorusSpeedTimer and the object behind this.hTimer was alive even after the ship's doom by this.harvester.temperature = 1.1. Does the timer stay alive, because something is still referring to it?

In another case I did not refer to the timer and blew the ship up, while in torus transit (running timer). The result:
Exception: TypeError: this.ship is undefined
Active script: Solar Harvester AI 0.1.0
solarHarvesterAI.js, line 50:
var timer = this.ship.AIScript._solarHarvesterTorusSpeedTimer;

Over and over again, every 0.25 seconds.

I don't want to create old timers or even still running once for each ship I launch with this AI.

I also tried:
this.entityDestroyed = function()
{
if (this.ship._solarHarvesterTorusSpeedTimer) {
if (this.ship._solarHarvesterTorusSpeedTimer.isRunning) this.ship._solarHarvesterTorusSpeedTimer.stop();
delete this.ship._solarHarvesterTorusSpeedTimer;
}
}

, but at this point this.ship is also not referable anymore.

Is there a method (way of scripting, not a certain function) you use, to make sure timers in priorityAIs die as they should?
User avatar
Svengali
Commander
Commander
Posts: 2370
Joined: Sat Oct 20, 2007 2:52 pm

Re: Scripters cove

Post by Svengali »

Timers in ship scripts? Use .shipDied and .shipRemoved instead to clean up.
And you are right .entityDestroyed is usally to late.
ocz
Deadly
Deadly
Posts: 175
Joined: Tue Nov 10, 2015 1:59 pm

Re: Scripters cove

Post by ocz »

I rewrote this.ship._solarHarvesterTorusSpeedTimer to this._solarHarvesterTorusSpeedTimer and therefore also changed var timer = this.ship._solarHarvesterTorusSpeedTimer; to var timer = this.ship.AIScript._solarHarvesterTorusSpeedTimer; and this.ship._solarHarvesterTorusSpeedTimer.start(); to this.ship.AIScript._solarHarvesterTorusSpeedTimer.start();

As the timer now hides behind a property of the custom AIscript, it is also still reachable for the this.entityDestroyed method after the ship is no more.

I tested the behavior:

Code: Select all

this.entityDestroyed = function()
{
	log(this._solarHarvesterTorusSpeedTimer);
	if (this._solarHarvesterTorusSpeedTimer) {
		if (this._solarHarvesterTorusSpeedTimer.isRunning) {
			
			this._solarHarvesterTorusSpeedTimer.stop();
			log("stopped");
		}
		
		delete this._solarHarvesterTorusSpeedTimer;
		log(this._solarHarvesterTorusSpeedTimer);
	}
}
Resulting in:
------------------------
[color=#0000FF][b]> this.harvester.temperature = 1.1[/b][/color]
[color=#009000]1.1[/color]
[color=#000000][Timer nextTime: 462.058, interval: 0.25, running, function: anonymous]

stopped[/color]


------------------------
So, as the final message of log(this._solarHarvesterTorusSpeedTimer) is missing in the log I assume, the timer is history, or at least food for the garbage collector.

@Svengali: For now this works out for me, but I really believe, that timers that manipulate npc-ships and are created for them in first place belong into their objects. :) I'll look into .shipDied and .shipRemoved methods.
User avatar
phkb
Impressively Grand Sub-Admiral
Impressively Grand Sub-Admiral
Posts: 4750
Joined: Tue Jan 21, 2014 10:37 pm
Location: Writing more OXPs, because the world needs more OXPs.

Re: Scripters cove

Post by phkb »

I want to create a group of pirates and have them sit (or patrol) a certain region of space, waiting for the player to show up, at which point they should attack immediately. I can create the pirates OK, but it's getting them to sit still or remain in the area that I'm struggling with.

I've tried:

Code: Select all

pirateship.performStop();
but they still seem to get it into their head to motor off somewhere.
User avatar
cim
Quite Grand Sub-Admiral
Quite Grand Sub-Admiral
Posts: 4072
Joined: Fri Nov 11, 2011 6:19 pm

Re: Scripters cove

Post by cim »

phkb wrote:
I want to create a group of pirates and have them sit (or patrol) a certain region of space, waiting for the player to show up, at which point they should attack immediately. I can create the pirates OK, but it's getting them to sit still or remain in the area that I'm struggling with.

I've tried:

Code: Select all

pirateship.performStop();
but they still seem to get it into their head to motor off somewhere.
The standard pirate AI will make the group leader take them to a pirate lurking point. If none is set, and they aren't already on a main lane, the leader will pick a position on one of the lanes.

To set your own lurk position, wait until their AI has initialised (a second will do) and then do

Code: Select all

pirate.AIScript.oolite_priorityai.setParameter("oolite_pirateLurk", position);
pirate.AIScript.oolite_priorityai.reconsiderNow();
for each ship in the pirate group, starting with the group leader.

performStop() will tell them to cut speed to zero - and they will - but on the next AI reconsideration they'll be off again.

...alternatively, give them an AI that's not the standard pirate AI, which you will need to do anyway to force an unconditional attack on the player.
User avatar
phkb
Impressively Grand Sub-Admiral
Impressively Grand Sub-Admiral
Posts: 4750
Joined: Tue Jan 21, 2014 10:37 pm
Location: Writing more OXPs, because the world needs more OXPs.

Re: Scripters cove

Post by phkb »

Thanks for that previous reply, cim.

Another question, this time for someone who understands (or maybe only kind of understands) vectors. I want to create a entity and then send it on it's way at high speed in a random direction, but I don't want the random direction to be into the sun or planet. If I have a starting position set, how do I set the heading and velocity?
Post Reply