Advanced Mining Script Alpha Tests

The place to discuss scripting and game modifications for X Rebirth.

Moderators: Scripting / Modding Moderators, Moderators for English X Forum

bradines
Posts: 31
Joined: Fri, 27. Mar 15, 20:58

Advanced Mining Script Alpha Tests

Post by bradines »

My Brother and I have made a new mining script... we have split the mining function into 3 parts. 1. Targeting and Movement. 2. Laser Target Selection and Firing. 3. Drone Resource Collection.

Its far more effective than the basic mining mod and the sensible miners mod. It targets the closest asteroid of the resource it is requested to mine before moving then moves to it. saving time. the script separation means that drones don't wait on gun calculations they are independent so they respond faster.

It has only 2 problems so far... 1. movement... we think when it tries to fire the engines it messes up and causes the crash.... working on proof.
2. each of the parts are a different script and run independently, each character can only have 1 script running or well that's what it seems so this ship can't repair or defend itself.... we need a way to add at least 2 specialists that can support running the scripts to leave the rest of the crew alone...

any help adding new crew to the game would be appreciated. along with other solutions... ps this script also works as an anti missile script...
UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader »

why not run your Firing Script on top of the DOs Stack with <run_interrupt_script /> and automatically return control to the default DO script if the need should arise? (eg enemies detected) - would save complications because the Target List is shared between Turrets and another additional Entity may confuse the Game.
similiar for the Engineer - just let him do the drone management while there is nothing to repair instead of waiting idly.

of course the Captain should regulary check if he needs to restart these Scripts on his co-workers, otherwise it will only work until the 1st attack. In case of Enemy Attack he should switch to an Fighting Script anyway... and when its over re-start the DO Script and resume Mining.
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)
bradines
Posts: 31
Joined: Fri, 27. Mar 15, 20:58

Post by bradines »

i actually would love to do that.... im not 100% sure how to detect some of those states...

1. how do i detect enemies?
2. how do i detect damage to the ship that is repairable... because damage is not always repairable by the engineer...
3. how do i stop and return the default scripts to normal when i give the captain a new order, we just found that if i order the ship to follow me the mining continues but he now follows my ship...
4. what is the default script used by the DO? i think the default repair script for engineer is like engineer.player right?
bradines
Posts: 31
Joined: Fri, 27. Mar 15, 20:58

Post by bradines »

this is the script that i think the captain is running.
<?xml version="1.0" encoding="iso-8859-1"?>
<aiscript name="advanced_mining.ship.collect" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="aiscripts.xsd">
<params>
<param name="zone"/>
<param name="ware"/>
<param name="secwares"/>
<param name="priority" default="'shooting'" />
<param name="debugchance" default="100" />

</params>
<attention min="visible">
<actions>

<set_value name="$dronelaunchdelay" exact="3s" comment="the minimum delay between two drone launches"/>
<set_value name="$gathertime" min="172s" max="188s" comment="the time spent to gather resources at a certain location (gases only)"/>
<set_value name="$traveltime" min="76s" max="84s" comment="the time between gathering at two different locations (gases only)"/>

<run_script name="'move.undock'"/>

<stop_moving object="this.ship" immediate="false"/>

<run_script name="'lib.recall.drones'">
<param name="timeout" value="2s"/>
</run_script>

<!-- Find a safe place to jump to in zone -->
<get_safe_pos result="$destination" zone="$zone" radius="this.ship.size" min="1km" max="35km" />

<!-- Move to destination zone -->
<do_if value="this.ship.zone != $zone">
<debug_text text="'Go mining to zone: ' + $zone.knownname" chance="$debugchance" />
<!-- If the zone to mine is a highway -->
<do_if value="$zone.isclass.highway">
<debug_text text="'Error moving to %1. This zone is a highway'" />
</do_if>
<run_script name="'move.generic'">
<param name="destination" value="$zone"/>
<param name="endintargetzone" value="true" />
<param name="debugchance" value="$debugchance"/>
</run_script>
</do_if>

<label name="start" />

<!-- gas mining -->
<do_if value="$ware.tags.indexof.{tag.liquid}">
<!-- chance to skip initial movement -->
<do_if value="true" chance="$gathertime / ($gathertime + $traveltime) * 100">
<set_value name="$skipmovement" exact="true"/>
</do_if>
<do_else>
<set_value name="$skipmovement" exact="false"/>
</do_else>
<set_value name="$gathercounter" exact="0s"/>

<!-- loop as long as there is at least 5% free cargo space -->
<do_while value="this.ship.cargo.{$ware}.free gt (0.05 * this.ship.cargo.{$ware}.max)">

<!-- Command action -->
<set_command_action commandaction="commandaction.searchingresources" />
<!-- Zone no longer exists -->
<do_if value="not $zone.exists">
<return value="'aborted'" />
</do_if>
<!-- Drone launchpad/drones destroyed -->
<do_if value="not this.ship.units.collect.{$ware}.count">
<return value="'nodrones'" />
</do_if>

<do_if value="$skipmovement" exact="false">
<do_if value="this.ship.distanceto.{$destination} lt 4km">
<debug_text text="player.age+' destination almost reached, creating a new destination'" chance="$debugchance"/>
<get_safe_pos result="$destination" zone="$zone" radius="this.ship.size" min="1km" max="35km" />
</do_if>
<debug_text text="player.age+' movement started (destination: '+this.ship.distanceto.{$destination}+'m)'" chance="$debugchance"/>
<move_to object="this.ship" destination="this.ship.zone" finishonapproach="true" forceposition="false">
<position value="$destination"/>
<interrupt_after_time time="1s"/>
</move_to>
<wait exact="$traveltime"/>
<debug_text text="player.age+' movement stopped, preparing to mine'" chance="$debugchance"/>
<stop_moving object="this.ship" immediate="false"/>
<wait min="4s" max="6s"/>
</do_if>
<do_else>
<set_value name="$skipmovement" exact="false"/>
</do_else>
<!-- launch drones to collect gas -->
<debug_text text="player.age+' starting to launch drones'" chance="$debugchance"/>
<set_value name="$gatherstart" exact="player.age"/>
<do_while value="player.age lt ($gatherstart + $gathertime)">
<do_if value="this.ship.cargo.{$ware}.free le (0.05 * this.ship.cargo.{$ware}.max)">
<break/>
</do_if>
<launch_drone name="$drone" object="this.ship" group="unitcategory.gascollector" exact="1"/>
<do_if value="$drone.isoperational">
<start_script name="'mining.ship.drone'" object="$drone.pilot">
<param name="homebase" value="this.ship"/>
<param name="ware" value="$ware"/>
</start_script>
</do_if>
<wait exact="$dronelaunchdelay"/>
<set_value name="$gathercounter" exact="$gathercounter + $dronelaunchdelay" />
<!-- gas gathering uses low attention mechanic -->
<do_if value="$gathercounter ge 15s">
<set_value name="$gathercounter" exact="15s" />
<do_if value="($gatherstart + $traveltime) lt player.age">
<get_resource_gatherrate name="$gatherrate" refobject="this.ship" zone="$zone" ware="$ware"/>
<set_value name="$gathered" min="$gatherrate * $gathercounter * 0.75" max="$gatherrate * $gathercounter * 1.25"/>
<deplete_yield zone="$zone" container="this.ship" ware="$ware" amount="$gathered"/>
<debug_text text="player.age + ' collected %1 units of %2 (%3 units/s on average)'.[$gathered, $ware, $gatherrate]" chance="$debugchance"/>
<set_value name="$gathercounter" exact="0"/>
</do_if>
</do_if>
</do_while>
<debug_text text="player.age+' stop launching drones'" chance="$debugchance"/>
</do_while>
<debug_text text="player.age+' less than 5% free cargo space'" chance="$debugchance"/>
</do_if>
<do_elseif value="this.ship.isclass.ship_xl or this.ship.isclass.ship_l" comment="Mineral mining (capital ships)">

<set_value name="$MaxMiningFiringRange" exact="2500"/>
<set_value name="$dronemaxdistance" exact="4000"/>

<do_if value="this.ship.defencenpc.exists">
<start_script name="'mining.ship.fireturrets'" object="this.ship.defencenpc">
<param name="ware" value="$ware" />
<param name="MaxMiningFiringRange" value="$MaxMiningFiringRange" />
</start_script>
</do_if>
<do_else>
<write_to_logbook category="general" text="this.ship.knownname +' can not activate the mining turrets do to no defence officer'"/>
</do_else>

<do_if value="this.container.specialistlogisticalofficer.exists">
<start_script name="'mining.ship.dronebay'" object="this.container.specialistlogisticalofficer">
<param name="ware" value="$ware" />
<param name="dronemaxdistance" value="$dronemaxdistance" />
</start_script>
</do_if>
<do_else>
<write_to_logbook category="general" text="this.ship.knownname +' can not activate the mining dronebay do to no logistical officer'"/>
</do_else>


<set_value name="$moving" exact="false"/>
<stop_moving object="this.ship" immediate="false"/>

<!-- loop as long as there is free cargo space -->
<do_while value="this.ship.cargo.{$ware}.free gt 0">
<!-- Command action -->
<set_command_action commandaction="commandaction.searchingresources" />

<!-- Zone no longer exists -->
<do_if value="not $zone.exists">
<debug_text text="$zone.exists + ' zone name is ' + '$zone.knownname" chance="$debugchance"/>
<return value="'aborted'" />
</do_if>

<!-- Return if ship can not do any of the mining tasks -->
<!-- operational mining turrets ? -->
<do_if value="not @$turrets.{1}.exists" comment="check with exists, because the disappear in low attention">
<find_object_component object="this.ship" name="$turrets" multiple="true" class="class.turret" weapontype="mining" />
</do_if>

<set_value name="$turretsgoodcount" exact="0"/>
<do_all exact="$turrets.count" counter="$i" reverse="true">
<do_if value="$turrets.{$i}.isoperational" >
<set_value name="$turretsgoodcount" exact="$turretsgoodcount + 1"/>
</do_if>
</do_all>

<!-- operational drone pad ? -->

<find_object_component name="$dronelaunchpad" object="this.ship" class="class.dronelaunchpad" functional="true" />
<!-- Return if ship can not do any of the mining tasks -->

<!-- operational mining drones ? -->

<set_value name="$drones" exact="null"/>
<add_to_group groupname="$drones" list="this.ship.subordinates" comment="use a group to handle the destruction/dock of drones" />

<!-- Filter subordinates to get only drones -->
<do_all exact="$drones.count" counter="$i" reverse="true">
<do_if value="not $drones.{$i}.isclass.drone">
<remove_from_group group="$drones" object="$drones.{$i}" />
</do_if>
</do_all>

<!-- Drone launchpad/drones destroyed and the mining turrets -->
<do_if value="((this.ship.units.collect.{$ware}.count le 0) or ((not $dronelaunchpad.isoperational) and (not this.container.engineer) ) ) and ((($turretsgoodcount le 0) and (not this.container.engineer)) or ($turrets.count le 0))">
<write_to_logbook category="general" text="this.ship.knownname +' can not mine. It has no drone or operational donebay or mining turrents or enginner to repair the damaged components.'"/>

<return value="'nodrones'" />
</do_if>

<find_asteroid_in_cluster name="$asteroids" cluster="this.cluster" refobject="this.ship" canpickup="false" multiple="true" maxdistance="$MaxMiningFiringRange" viewangle="360deg" ware="$ware" />
<set_value name="$asteroidsaroundtheship" exact="$asteroids.count"/>

<!-- check to make sure the guns can hit the targets -->
<do_if value="$asteroids.count gt 0">
<!-- Check if the target can be hit -->
<do_if value="not @$turrets.{1}.exists" comment="check with exists, because the disappear in low attention">
<find_object_component object="this.ship" name="$turrets" multiple="true" class="class.turret" weapontype="mining" />
</do_if>
<do_all exact="$asteroids.count" counter="$x" reverse="true" >
<set_value name="$view" exact="false" />
<do_all exact="$turrets.count" counter="$i" reverse="true" comment="in reverse because usually the front turret is the last, so the iteration breaks earlier">
<check_line_of_sight object="$turrets.{$i}" target="$asteroids.{$i}" name="$result" />
<do_if value="$result and $turrets.{$i}.distanceto.{$asteroids.{$i}} lt $MaxMiningFiringRange">
<set_value name="$view" exact="true" />
<break />
</do_if>
</do_all>
<do_if value="not $view">
<remove_value name="$asteroids.{$x}" />
</do_if>
</do_all>
</do_if>

<find_asteroid_in_cluster name="$pickup" cluster="this.cluster" refobject="this.ship" canpickup="true" multiple="true" maxdistance="$dronemaxdistance" viewangle="360deg" ware="$ware" />


<do_if value="$moving">
<!--Stop rotate or move the ship the guns should be able to hit the asteroid-->

<do_if value="this.ship.distanceto.{$target.{1}} lt this.ship.size * 2">

<set_value name="$preferredtarget" exact="null"/>
<write_to_logbook category="general" text="this.ship.knownname+' is now in range of target ' + $target.{1}.knownname" />
<set_value name="$moving" exact="false"/>
<stop_moving object="this.ship" immediate="false"/>
</do_if>
</do_if>
<do_elseif value="($asteroidsaroundtheship le 0) or ($turretsgoodcount le 0)">
<!-- Need to move because there is no targets in range of the turrets or this is a drone ship miner -->
<do_if value="(($pickup.count le 0) and ($drones.count le 0) ) or (this.ship.units.collect.{$ware}.count le 0) or (not $dronelaunchpad.isoperational)">
<!-- Need to move because there is no pebbles in range to pick up by the drone ships or this is a mining laser ship -->
<find_closest_resource ware="$ware" refobject="this.ship.commander" zone="$zone" wares="$secwares" minamount="1" />

<write_to_logbook category="general" text="this.ship.knownname+' is moving to start ' +$priority + ' at another site'" />

<do_if value="this.zone == $zone" >
<do_if value="($turretsgoodcount le 0) or ($priority == 'collecting')" >

<!-- Look for pebbles -->
<find_asteroid_in_cluster name="$target" cluster="this.cluster" refobject="this.ship" canpickup="true" multiple="true" maxdistance="$MaxMiningFiringRange" viewangle="360deg" ware="$ware" />
<set_value name="$targeting_distance" exact="$dronemaxdistance"/>
<set_value name="$targeting_distance_to_great" exact="5000000"/> <!--Sanity check -->

<do_while value="$target.count le 0">

<find_asteroid_in_cluster name="$target" cluster="this.cluster" refobject="this.ship" canpickup="true" multiple="true" maxdistance="$targeting_distance" viewangle="360deg" ware="$ware" />


<do_if value="$targeting_distance ge $targeting_distance_to_great">
<break />
</do_if>
<set_value name="$targeting_distance" exact="$targeting_distance * 2" max="$targeting_distance_to_great"/>
<debug_text text="this.cluster+' '+($targeting_distance)+'m scaning'" chance="$debugchance"/>

</do_while>

<!-- if you where not able the find any pebbles asteroids look for asteroids-->
<set_value name="$targeting_distance" exact="$MaxMiningFiringRange"/>
<set_value name="$targeting_distance_to_great" exact="5000000"/> <!--Sanity check -->

<do_while value="$target.count le 0">

<find_asteroid_in_cluster name="$target" cluster="this.cluster" refobject="this.ship" canpickup="false" multiple="true" maxdistance="$targeting_distance" viewangle="360deg" ware="$ware" />


<do_if value="$targeting_distance ge $targeting_distance_to_great">
<break />
</do_if>
<set_value name="$targeting_distance" exact="$targeting_distance * 2" max="$targeting_distance_to_great"/>
<debug_text text="this.cluster+' '+($targeting_distance)+'m scaning'" chance="$debugchance"/>

</do_while>


</do_if>
<do_elseif value="(this.ship.units.collect.{$ware}.count le 0) or ($priority == 'shooting')" >

<!-- Look for asteroids -->
<find_asteroid_in_cluster name="$target" cluster="this.cluster" refobject="this.ship" canpickup="false" multiple="true" maxdistance="$MaxMiningFiringRange" viewangle="360deg" ware="$ware" />
<set_value name="$targeting_distance" exact="$MaxMiningFiringRange"/>
<set_value name="$targeting_distance_to_great" exact="5000000"/> <!--Sanity check -->

<do_while value="$target.count le 0">

<find_asteroid_in_cluster name="$target" cluster="this.cluster" refobject="this.ship" canpickup="false" multiple="true" maxdistance="$targeting_distance" viewangle="360deg" ware="$ware" />


<do_if value="$targeting_distance ge $targeting_distance_to_great">
<break />
</do_if>
<set_value name="$targeting_distance" exact="$targeting_distance * 2" max="$targeting_distance_to_great"/>
<debug_text text="this.cluster+' '+($targeting_distance)+'m scaning'" chance="$debugchance"/>

</do_while>

<!-- if you where not able the find any asteroids look for pebbles-->
<set_value name="$targeting_distance" exact="$dronemaxdistance"/>
<set_value name="$targeting_distance_to_great" exact="5000000"/> <!--Sanity check -->

<do_while value="$target.count le 0">

<find_asteroid_in_cluster name="$target" cluster="this.cluster" refobject="this.ship" canpickup="true" multiple="true" maxdistance="$targeting_distance" viewangle="360deg" ware="$ware" />


<do_if value="$targeting_distance ge $targeting_distance_to_great">
<break />
</do_if>
<set_value name="$targeting_distance" exact="$targeting_distance * 2" max="$targeting_distance_to_great"/>
<debug_text text="this.cluster+' '+($targeting_distance)+'m scaning'" chance="$debugchance"/>

</do_while>

</do_elseif>

<do_if value="$target.{1}.exists">
<set_value name="$preferredtarget" exact="$target.{1}"/>
<write_to_logbook category="general" text="this.ship.knownname+' is moving to rock ' +$preferredtarget" />

<set_value name="$moving" exact="true"/>
<start_boost object="this.ship" />
<move_to object="this.ship" destination="$preferredtarget.zone" finishonapproach="true" forceposition="false" abortpath="false" usehighways="false">
<position object="$preferredtarget" />
<interrupt_after_time time="10s"/>
</move_to>
<stop_boost object="this.ship" />
</do_if>
</do_if>
<do_else> <!--We need to move to another zone-->
<write_to_logbook category="general" text="this.ship.knownname+' is moving to ' +$zone.knownname" />

<run_script name="'move.generic'">
<param name="destination" value="$zone" />
<param name="endintargetzone" value="true" />
<param name="debugchance" value="$debugchance" />
</run_script>
</do_else>

</do_if>

</do_elseif>
<do_elseif value="$asteroids.count le 0"> <!--Turn the ship to the face the asteroid that is in a blind spot-->
<write_to_logbook category="general" text="this.ship.knownname+' is rotating to hit an asteroid. There are ' + $asteroidsaroundtheship +' around the ship'" />

<set_value name="$moving" exact="true"/>
<!--Rotate the ship to the first asteroid you find-->
<find_asteroid_in_cluster name="$target" cluster="this.cluster" refobject="this.ship" canpickup="false" multiple="true" maxdistance="$MaxMiningFiringRange" viewangle="360deg" ware="$ware" />

<set_value name="$preferredtarget" exact="$target.{1}"/>
<!-- first try to rotate on the spot -->
<debug_text text="'rotating towards asteroid: ' + $target.{1}" chance="$debugchance"/>
<create_orientation name="$rot" orientation="look_at" refobject="$preferredtarget">
<position object="this.ship" />
</create_orientation>
<move_to object="this.ship" destination="$preferredtarget.zone" finishonapproach="true" forceposition="false" forcerotation="true" abortpath="true" usehighways="false">
<position object="this.ship" max="this.ship.size * 2" />
<rotation value="$rot" />
<interrupt_after_time time="500ms" />
</move_to>

<do_if value="$preferredtarget.exists">
<debug_text text="'flying to asteroid: ' + $preferredtarget" chance="$debugchance"/>
<move_to object="this.ship" destination="$preferredtarget.zone" finishonapproach="true" forceposition="false" abortpath="false" usehighways="false">
<position object="$preferredtarget" />
<interrupt_after_time time="10s"/>
</move_to>
</do_if>
</do_elseif>

<wait exact="1s"/>
</do_while>

<abort_scripts entity="this.ship.defencenpc" />
<abort_scripts entity="this.container.specialistlogisticalofficer" />

<debug_text text="player.age+' cargo space full'" chance="$debugchance"/>

</do_elseif>
<do_else> <!-- mineral mining (medium ships) -->
<set_value name="$attackposition" exact="false"/>
<do_while value="this.ship.cargo.{$ware}.free gt (0.05 * this.ship.cargo.{$ware}.max)">

<!-- Command action -->
<set_command_action commandaction="commandaction.searchingresources" />

<!-- Zone no longer exists -->
<do_if value="not $zone.exists">
<return value="'aborted'" />
</do_if>
<!-- Drone launchpad/drones destroyed -->
<do_if value="not this.ship.units.collect.{$ware}.count">
<return value="'nodrones'" />
</do_if>

<set_value name="$checkware" exact="$ware" />
<!-- 10% chance to gather secondary wares that can be mined -->
<do_if value="@$secwares.count" chance="10">
<set_value name="$tryware" exact="$secwares.random"/>
<!-- evaluate if should use a secondary ware -->
<do_if value="(this.ship.units.collect.{$tryware}.count and this.ship.cargo.{$tryware}.free)">
<debug_text text="'IS mining: try other ware (%1)'.[$tryware]" chance="$debugchance" />
<set_value name="$checkware" exact="$tryware"/>
</do_if>
<remove_value name="$tryware" />
</do_if>
<!-- find pickup (filtered by ownership) and target -->
<set_value name="$pickuptarget" exact="false"/>
<set_value name="$skill" exact="(this.combinedskill - 50) * 3" />

<!-- Small asteroids to pick up -->
<find_asteroid_in_cluster name="$pickup" cluster="this.cluster" refobject="this.ship" canpickup="true" multiple="true" maxdistance="2km" ware="$checkware" viewangle="360deg" />
<do_all exact="$pickup.count" counter="$i" reverse="true">
<do_if value="$pickup.{$i}.owner">
<remove_value name="$pickup.{$i}" />
</do_if>
<do_elseif value="not $pickup.{$i}.canbepickedup">
<debug_text text="'%1 in %2 cannot be picked up!'.[$pickup.{$i}, $pickup.{$i}.zone.knownname]" chance="$debugchance"/>
<remove_value name="$pickup.{$i}" />
</do_elseif>
<do_elseif value="$pickup.{$i}.wares.{$checkware}.count le 0" chance="$skill">
<remove_value name="$pickup.{$i}" />
</do_elseif>
</do_all>
<!-- evaluate movement -->
<do_if value="$pickup.count le this.ship.units.collect.{$checkware}.count">
<!-- No target -->
<do_if value="not @$target.exists">
<!-- find asteroids and the best target -->
<find_asteroid_in_cluster name="$asteroids" cluster="this.cluster" refobject="this.ship" canpickup="false" multiple="true" maxdistance="3km" ware="$checkware" viewangle="180deg"/>

<do_if value="$asteroids.count" min="1">
<set_value name="$target" exact="$asteroids.{1}"/>
<set_value name="$bestasteroid" exact="$asteroids.{1}.hull"/>
<do_all exact="$asteroids.count" counter="$i">
<do_if value="$asteroids.{$i}.hull lt $bestasteroid">
<set_value name="$target" exact="$asteroids.{$i}"/>
<set_value name="$bestasteroid" exact="$asteroids.{$i}.hull"/>
</do_if>
</do_all>
<debug_text text="'%1 new target [pickup count: %2, asteroid count: %3 (%4)]'.[player.age, $pickup.count, $asteroids.count, $bestasteroid]" chance="$debugchance"/>
</do_if>
<do_else>
<!-- Find again with bigger range -->
<find_asteroid_in_cluster name="$target" cluster="this.cluster" refobject="this.ship" canpickup="false" multiple="false" maxdistance="55km" ware="$checkware" viewangle="360deg"/>
</do_else>
</do_if>

<!-- Target exists -->
<do_if value="$target.exists">
<!-- Set asteroid persistence -->
<set_region_object_persistence object="$target" />
<!-- Distance check -->
<do_if value="this.ship.distanceto.{$target} - ($target.size/2.f)" min="1200m">
<!-- the target is out of firing range, we have to move closer -->
<debug_text text="player.age+' target is out of range ('+ (this.ship.distanceto.{$target} - ($target.size/2.f)) +'m)'" chance="$debugchance"/>
<move_to object="this.ship" destination="$target.zone" forceposition="false" finishonapproach="true">
<position object="$target" />
<interrupt_after_time time="1s"/>
</move_to>
</do_if>
<do_else>
<set_value name="$attackposition" exact="true"/>
<shoot_at object="this.ship" slot="tag.primary_slot" target="$target" tolerance="12.0deg" weapontype="mining" />
<!-- stop and rotate -->
<debug_text text="player.age+' target is now in range ('+ (this.ship.distanceto.{$target} - ($target.size/2.f)) +'m)'" chance="$debugchance"/>
<move_to object="this.ship" destination="$target.zone" forcerotation="true" forcesteering="true" flightbehaviour="flightbehaviour.mining">
<position object="$target" max="50m" />
<interrupt_after_time time="1s" />
</move_to>
</do_else>
</do_if>

<!-- No Target - Attack position -->
<do_elseif value="not @$target.exists and $attackposition">
<!-- We where shooting the asteroid -->
<set_value name="$attackposition" exact="false"/>
</do_elseif>

<!-- No Target - No Attack position -->
<do_elseif value="not @$target.exists and not $attackposition">
<!-- Reset state -->
<remove_value name="$target"/>
<stop_shooting object="this.ship" slot="tag.primary_slot"/>
<set_flight_control_model object="this.ship" flightcontrolmodel="flightcontrolmodel.spline" />
<!-- No more asteroids -->
<do_if value="not @$asteroids.count">
<!-- when no asteroid found and nothing to pickup-->
<do_if value="not $pickup.count">
<debug_text text="'no resources found, flying to random position'" chance="$debugchance" />

<get_safe_pos result="$destination" zone="$zone" radius="this.ship.size" min="1km" max="50km" />
<!-- Fly to a random pos in zone -->
<move_to object="this.ship" destination="$zone" sinceversion="1">
<position value="$destination"/>
<interrupt_after_time time="2min" />
</move_to>
</do_if>
</do_if>
</do_elseif>
</do_if>

<!-- launch drone to pick up the target -->
<do_if value="$pickup.count">
<set_value name="$pickuptarget" exact="$pickup.random"/>
<set_region_object_persistence object="$pickuptarget" persistent="true" />
<launch_drone name="$drone" object="this.ship" group="unitcategory.orecollector" exact="1"/>
<do_if value="$drone.isoperational">
<debug_text text="'%1 drone launched [pickup count: %2, asteroid count: %3]'.[player.age, $pickup.count, @$asteroids.count]" chance="$debugchance"/>
<start_script name="'mining.ship.drone'" object="$drone.pilot">
<param name="homebase" value="this.ship" />
<param name="target" value="$pickuptarget"/>
</start_script>
<set_owner object="$pickuptarget" faction="this.ship.owner"/>
</do_if>
<do_else>
<set_command_action commandaction="commandaction.waitingdrones" />
<debug_text text="'%1 no drone available [pickup count: %2, asteroid count: %3]'.[player.age, $pickup.count, @$asteroids.count]" chance="$debugchance"/>
</do_else>
</do_if>

<wait exact="$dronelaunchdelay"/>

</do_while>
</do_else>

<!-- Stop mining lasers -->
<stop_shooting object="this.ship" slot="tag.primary_slot" comment="for primary weapon" />
<cease_fire object="this.ship" weapontype="mining" comment="for turrets" />

<return value="'cargofull'" />

</actions>
</attention>
<attention min="unknown">
<actions>

<set_value name="$dronelaunchdelay" exact="3s" comment="the minimum delay between two drone launches"/>
<set_value name="$gathertime" min="172s" max="188s" comment="the time spent to gather resources at a certain location (gases only)"/>
<set_value name="$traveltime" min="76s" max="84s" comment="the time between gathering at two different locations (gases only)"/>

<run_script name="'move.undock'" sinceversion="4" />

<get_safe_pos result="$destination" zone="$zone" radius="this.ship.size" min="1km" max="35km" />

<!-- Move to destination zone -->
<do_if value="this.ship.zone != $zone">
<debug_text text="'Go mining to zone: ' + $zone.knownname" chance="$debugchance" />
<!-- If the zone to mine is a highway -->
<do_if value="$zone.isclass.highway">
<debug_text text="'Error moving to %1. This zone is a highway'" />
<!-- <resume label="start" /> -->
</do_if>
<run_script name="'move.generic'">
<param name="destination" value="$zone"/>
<param name="endintargetzone" value="true" />
<param name="debugchance" value="$debugchance"/>
</run_script>
</do_if>

<label name="start" />

<wait min="8s" max="12s" />
<do_while value="this.ship.cargo.{$ware}.free gt 0">

<!-- command action simulation -->
<do_any>
<set_command_action commandaction="commandaction.searchingresources" weight="60" />
<set_command_action commandaction="commandaction.flying" weight="40" />
</do_any>

<!-- Zone no longer exists -->
<do_if value="not $zone.exists">
<return value="'aborted'" />
</do_if>
<!-- Drone launchpad/drones destroyed -->
<do_if value="not this.ship.units.collect.{$ware}.count">
<return value="'nodrones'" />
</do_if>

<set_value name="$currentware" exact="$ware" />
<!-- 20% chance that we try to collect one of the other resources that can be gathered in this zone if they are useful to our homebase, $tryware can be the same as $ware -->
<do_if value="@$secwares.count" chance="10">
<set_value name="$tryware" exact="$secwares.random"/>
<!-- evaluate if should use a secondary ware -->
<do_if value="(this.ship.units.collect.{$tryware}.count and this.ship.cargo.{$tryware}.free)">
<debug_text text="'OOZ mining: try other ware (%1)'.[$tryware]" chance="$debugchance" />
<set_value name="$currentware" exact="$tryware"/>
</do_if>
<remove_value name="$tryware" />
</do_if>
<get_resource_gatherrate name="$gatherrate" refobject="this.ship" zone="$zone" ware="$currentware" />
<do_if value="$gatherrate" max="0">
<debug_text text="player.age + ' WARNING: gatherrate for %1 in zone %2 is %4'.[$currentware, $zone.knownname, $gatherrate]" chance="$debugchance" />
</do_if>
<set_value name="$gatherstart" exact="player.age" />
<!-- smaller mining ships need some time to gather more than zero resources -->
<do_if value="this.ship.isclass.ship_xl or this.ship.isclass.ship_l">
<wait min="16s" max="24s"/>
</do_if>
<do_else>
<wait min="112s" max="128s"/>
</do_else>
<set_value name="$currentgathertime" exact="player.age - $gatherstart" />
<set_value name="$gathered" exact="$currentgathertime * $gatherrate" />
<do_if value="this.ship.cargo.{$currentware}.free lt $gathered">
<set_value name="$gathered" exact="this.ship.cargo.{$currentware}.free" />
</do_if>
<deplete_yield zone="$zone" container="this.ship" ware="$currentware" amount="$gathered" />
<debug_text text="player.age + ' collected %1 units of %2 in zone %3 in %4 seconds (%5 units/s)'.[$gathered, $currentware, $zone.knownname, $currentgathertime, $gatherrate]" chance="$debugchance" />

</do_while>

<debug_text text="player.age + ' %1(job: \'%2\') completed gather-run of %3 in %4. Cargo: %5'.[this.ship.knownname, this.ship.job, $ware, $zone.knownname, this.ship.cargo.list]" chance="$debugchance" />

<return value="'cargofull'" />

</actions>
</attention>
</aiscript>
bm01
Posts: 421
Joined: Wed, 22. Jul 09, 22:31
x4

Post by bm01 »

Would be better with some indentation :D
bradines wrote:1. how do i detect enemies?
2. how do i detect damage to the ship that is repairable... because damage is not always repairable by the engineer...
3. how do i stop and return the default scripts to normal when i give the captain a new order, we just found that if i order the ship to follow me the mining continues but he now follows my ship...
4. what is the default script used by the DO? i think the default repair script for engineer is like engineer.player right?
1. You would have to check the gravidar. Here's what I personally use:

Code: Select all

<find_gravidar_contact name="$enemies" multiple="true" mayattack="parent.$ship" functional="true" object="parent.$ship">
  <match_distance max="10km" object="parent.$ship"/>
</find_gravidar_contact>
"name" will be the result of the search (a list in that case).
See aiscripts.xsd for more information on that function.

2. That is more complicated. I personally check health at regular intervals and compare the current one with the previous one, then you can check how much the Engineer can repair in 'engineer.ai' and use the same formula. But it's a little different and not something you should do in an AI script.
There's also an event you could use in the interrupt node, see <event_object_attacked object="this.ship"/>. Note that however you can't do what you want in an interrupt node, blocking actions aren't allowed (you can however abort scripts and resume at some label in the actions node). Again, you would have to use the same formula as in 'engineer.ai'.
Also, if your ship has a Defence Officer, you could launch a custom event (which would be listened by other entities in their interrupt nodes) from its main "target acquisition" loop if the hull is below a certain threshold (again, same formula). This would give the same result but would allow you to differentiate friendly fire (since only hostiles are added to that list) and know when the ship is no longer attacked more easily (once the list is empty).

3. Not sure if I understand the question. All ships under player commandment (squad) run 'player.default', which is interrupted every time you give them a new order, subsequent scripts are aborted and 'player.default' is resumed at some label. They should stop mining.

4. 'engineer.player' is only for the engineer aboard the Skunk, so it's the other one. As for the Defence Officer, it's 'fight.defend.capital' but it runs 'fight.attack.object.capital' if it's on attack mode or if it's being attacked (and this is where you would do what I suggested in 2.).
bradines
Posts: 31
Joined: Fri, 27. Mar 15, 20:58

Post by bradines »

thanks man i will try that out..


i have done some things to address the problems and released this so people can give me feed back.

http://steamcommunity.com/sharedfiles/f ... =416688537

its only effecting capital ships and solid rocks at the moment.

most of the bugs i have seen are from the turret targeting stuff where it suffers the same problem as other turrets, it thinks it can hit something it can't... but ill work on that more later, just want to see what people think about it and where i could use some improvement.
Vim Razz
Posts: 1842
Joined: Tue, 2. Nov 10, 02:20
x4

Post by Vim Razz »

This is some awesome stuff that you guys have done so far.

In the current test version, you could restart the normal engineer and def officer's scripts in the <on_abort> section of the main script to solve the problem where they just keep mining after the stop order is given.


Or if you want to push things a bit farther.... :P I made a test-build version based on your description in the OP and some stuff I've been working on for one of my own projects:

https://www.dropbox.com/s/9fq5433wjoasc ... d.zip?dl=0

I haven't touched your core mining aiscript at all, but I've re-worked the framing and NPC handling.

I've also added in some robust tracking so that mods like mine can identify it more easily in order to not accidentally break it.


My specific suggestions are all labeled with "NOTE:" comments in the script with details about why I made each edit, but here's the general outline:

- This version requires 2 spare Pilots aboard the cap ship as passengers to work as the "specialists" for operating turrets and drones.
- I've set it up so that if you dock with 2 Pilots as passengers in the back of the Skunk and give the mining order face-to-face to the captain, then they'll be transferred down if there aren't enough pilots already onboard the cap-ship to run the scripts.
- the next time you give the order, the pilots should still be there so there's no need to dock again.
- or you can use my mod (in sig) or litauen's capital ship bridge mod to get the pilots onboard as passengers before issuing the order in the first place. up to you.

- If there aren't enough pilots available to run turrets + drones then the ship will run the vanilla mining script instead as a fallback measure.

- The ship's engineer isn't used in this one, so it just does it's repairs as normal.
- The defence officer will be put on ice while the turret operator is running the mining lasers, but will be restored to duty when the cargo bay is full or mining is interrupted.


So, anyway -- good luck and feel free to use any of the implementations in there you might like or find useful. This turned out to be a great test for some of the concepts that I've been experimenting with and I had a lot of fun with it.
bradines
Posts: 31
Joined: Fri, 27. Mar 15, 20:58

Post by bradines »

Vim Razz wrote:This is some awesome stuff that you guys have done so far.

In the current test version, you could restart the normal engineer and def officer's scripts in the <on_abort> section of the main script to solve the problem where they just keep mining after the stop order is given.


Or if you want to push things a bit farther.... :P I made a test-build version based on your description in the OP and some stuff I've been working on for one of my own projects:

https://www.dropbox.com/s/9fq5433wjoasc ... d.zip?dl=0

I haven't touched your core mining aiscript at all, but I've re-worked the framing and NPC handling.

I've also added in some robust tracking so that mods like mine can identify it more easily in order to not accidentally break it.


My specific suggestions are all labeled with "NOTE:" comments in the script with details about why I made each edit, but here's the general outline:

- This version requires 2 spare Pilots aboard the cap ship as passengers to work as the "specialists" for operating turrets and drones.
- I've set it up so that if you dock with 2 Pilots as passengers in the back of the Skunk and give the mining order face-to-face to the captain, then they'll be transferred down if there aren't enough pilots already onboard the cap-ship to run the scripts.
- the next time you give the order, the pilots should still be there so there's no need to dock again.
- or you can use my mod (in sig) or litauen's capital ship bridge mod to get the pilots onboard as passengers before issuing the order in the first place. up to you.

- If there aren't enough pilots available to run turrets + drones then the ship will run the vanilla mining script instead as a fallback measure.

- The ship's engineer isn't used in this one, so it just does it's repairs as normal.
- The defence officer will be put on ice while the turret operator is running the mining lasers, but will be restored to duty when the cargo bay is full or mining is interrupted.


So, anyway -- good luck and feel free to use any of the implementations in there you might like or find useful. This turned out to be a great test for some of the concepts that I've been experimenting with and I had a lot of fun with it.

we are reading through your files now... thanks for everything we appreciated the hand more than you know... im betting most of these suggestion will make it into the end version of the mod if we can't find a better way to run the scripts like tying them to turrets and drone bays...
bradines
Posts: 31
Joined: Fri, 27. Mar 15, 20:58

Post by bradines »

ok we made a update using Vims suggestions... and we have made a new to do list based on the tests.

THINGS TO TRY
1. Prioritization of Destroying EMPTY ROCKS for Mining Lasers. (maybe add a NEW List with only pebbles selected for destruction and have the guns shoot those first)
2. Mining Laser Targeting, we need a way to posible break out of the loop and shoot stuff closer in with out finishing the loop because we are busting up a lot of excees rocks.
3. Drone Launch Proceedure Changes: we need to try to pick up bigger pebbles first, would aid in fill up speed for smaller ships that can't transport all they mine. need to try to increase drone utalization...( am thinking we run ping out as far as we can till it is greater than the total number of mining drones or reaches max range, then we use the same method to jump out of the loop for the turrets to activate and add to the list at that range if the list count is greater at that current range than the current list size or something need to hash this out better)
4. Sector Clean Up: we shoudl make it so that if your mining a resource and their are pebbles of that kind already busted up in the sector we start mining there so we don't bust large sections of rocks all over the cluster causign a FPS drop.
5. removing the need for the 2 pilotsusing hidden actors as detailed by Vim... worth a look, maybe NPCs can use this method too if we do it right.




last night i think we solved issue number 1 on that list to a small degree.. we don't prioritize them but we improved the way we identify the waste rocks and add them to the targeting list... also we added that function directly to the firing script, the new function doesn't require looping so should improve system performance slightly.

we also addressed issue number 3 on that list to a degree, we change the drone collection list generation code so it will always try to generate a list greater than the number of drone on the ship...we have a much faster launch program than the default script but the hang up time between lists we killing us. we also made some changes to try to speed list transition up.

we will release last nights test code later this week, but right now we have a serious issue..our ability to mine rare rocks is questionable at best... when we find one in the sector we are golden and move to it quickly and destroy it... when we dont we get stuck and im not sure how we get stuck... we find a rock and we are in transit and then poof we lose the target and the move.generic just breaks down... or we never find a target at alll... we think it has something to do with how this command actually runs in the engine

<find_asteroid_in_cluster name="$asteroids" cluster="this.cluster" refobject="this.ship" canpickup="false" multiple="true" maxdistance="$MaxMiningFiringRange" viewangle="360deg" ware="$ware" />
(ps that that command is currently being fed the stuff for anti useless rock in that statement.)

we are really convinced that data is being omitted,or there is a range limitation codded into it to prevent searches like ore from over filling the list or to ensure that the amount of data it returns is with in reason. which is all well in good for common stuff, but when mining the rare recources this causes problems... and they solved with a random move to try to put stuff in range, we would prefer to just fly to the rocks if possible... i mean if we have to do the random fly thing i promise we will make that flight faster, but it just seems like such a waste.. because of a simple limitation.
UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader »

i just had a look into the NPC mining script ( mining.ship.collect ) and may have found the source of some of your problems:
Asteroids only exist when they can be seen by the Player (so inside current Zone and maybe the neighbour Zones? not sure what <attention min="visible" /> means but i think its between min="inzone" and min="insector"
in short only when Visible the Vanilla Scripts actually search for Rocks - otherwise they just deplete the Ressources slowly
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)
bradines
Posts: 31
Joined: Fri, 27. Mar 15, 20:58

Post by bradines »

i like what you found it kinda makes sense given our results and how the basic script works... if it can't "see" anything it flies and by doing so must "see" more rocks during its travels and be allowed to search them... ill pass this on to the rest of the team when they get ready to work this evening.

Return to “X Rebirth - Scripts and Modding”