It is a modified and simplified version of the Beamers from my Drake Technologies mod.
Code: Select all
<?xml version="1.0" ?>
<!DOCTYPE TranscendenceExtension
[
<!ENTITY unid912Hitscan "0xd912ffe0">
<!ENTITY ef912Null "0xd912ffe1">
<!ENTITY ef912RedLaser "0xd912ffe2">
<!ENTITY vt912HiddenLaser "0xd912ffe3">
<!ENTITY vt912VisibleLaser "0xd912ffe4">
<!ENTITY vt912FakeHiddenLaser "0xd912ffe5">
<!ENTITY vt912FakeVisibleLaser "0xd912ffe6">
<!ENTITY it912Hitscan "0xd912ffe7">
]>
; Made for Transcendence v1.6.2 or later.
<TranscendenceExtension UNID="&unid912Hitscan;"
apiVersion="28"
name="Hitscan Beam Weapon Tutorial"
credits="PM"
>
;- - - - - - - - - -
; Since we are using resources from the standard game, we need to include this library!
; Including libraries is the first thing we need to do before anything else in this file.
;- - - - - - - - - -
<Library unid="&unidHumanSpaceLibrary;"/>
;- - - - - - - - - -
; These are effects our beams will reference.
;- - - - - - - - - -
<Effect UNID="&ef912Null;"> <Null/> </Effect>
<Effect UNID="&ef912RedLaser;">
<Ray style="smooth" shape="oval" primaryColor="#ff0000" secondaryColor="#800000" length="60" width="12" intensity="35" />
</Effect>
;- - - - - - - - - -
; Our weapon's OnFireWeapon event will reference these types as a base for the beam segments that will be created.
; Each beam segment should last for one tick only. However, we do not use lifetime of 1 because such shots
; usually disappear as quickly as they are spawned. We use lifetime of 2 instead for all of them to make
; sure our beam segments persist for one tick.
;- - - - - - - - - -
<ItemType UNID="&vt912HiddenLaser;" virtual="true" >
<Weapon type="beam" damage="laser:1d4" lifetime="2" effect="&ef912Null;" />
</ItemType>
<ItemType UNID="&vt912VisibleLaser;" virtual="true" >
; NOTE: 'passthrough' is 1 because non-zero passthrough causes beam to be drawn over any object it touches.
; 1% chance of passthrough is a negligable chance for extra accidental damage. This is acceptable.
<Weapon type="beam" damage="laser:1d4" lifetime="2" passthrough="1" effect="&ef912RedLaser;" />
</ItemType>
;- - - - - - - - - -
; These next two have no***Hits, which prevents these types from hitting anything except other missiles.
; Ideally, these should be effects, not weapon types, but some effects do not support things a weapon type can.
; In other words, they are glorifed effects that have the side-effect of hitting and damaging other missiles.
; Aside from no***Hits and a different UNID, these two types mirror the previous two types above.
;- - - - - - - - - -
<ItemType UNID="&vt912FakeHiddenLaser;" virtual="true" >
<Weapon type="beam" damage="laser:1d4" lifetime="2" effect="&ef912Null;"
noImmobileHits="true" noImmutableHits="true" noShipHits="true" noStationHits="true" noWorldHits="true" />
</ItemType>
<ItemType UNID="&vt912FakeVisibleLaser;" virtual="true" >
<Weapon type="beam" damage="laser:1d4" lifetime="2" passthrough="1" effect="&ef912RedLaser;"
noImmobileHits="true" noImmutableHits="true" noShipHits="true" noStationHits="true" noWorldHits="true" />
</ItemType>
; The weapon will be given for free at the start of a game.
; Value will be zero so that the player cannot sell for quick cash.
; We do not want this weapon to appear anywhere else.
; Frequency is notrandom, and attribute includes CannotOrder.
<ItemType UNID="&it912Hitscan;"
name= "hitscan laser cannon"
attributes= "cannotOrder, energyWeapon, majorItem"
level= "2"
frequency= "notrandom"
value= "0"
mass= "1000"
description= "This weapon fires an FTL beam that simulates a laser in every way except speed."
>
<Image imageID="&rsItemsEI1;" imageX="96" imageY="0" imageWidth="96" imageHeight="96"/>
;- - - - - - - - - -
; NOTES!
;--------
; Without repeating, our beams last two frames or ticks at most.
; Use 'type' missile because we need to use missilespeed other than 100.
; 'damage' is used mainly for stats. Also used to calculate damage to attack in case of misfire, or to suppress in case attacker has Solon shield installed.
; 'lifetime' is 1 because AI needs this and missileSpeed to calculate aiming solution if an NPC uses any hitscan weapon.
; 'missileSpeed' is our beam range multiplied by 50. Since our beams have range 60, the result is 3000.
;- - - - - - - - - -
<Weapon
repeating= "9"
type= "missile"
damage= "laser:1d4"
fireRate= "60"
lifetime= "1"
missileSpeed= "3000"
powerUse= "30"
sound= "&snLaserCannon;"
>
</Weapon>
<Events>
; Called every time we fire our weapon.
<OnFireWeapon>
(block (shotType theVel maxRange)
;- - - - - - - - - -
; We will create many shots in a loop and add attacker's velocity to all of them!
; Therefore, called this function once and remember velocity instead of calling
; the function multiple times in a loop later.
;- - - - - - - - - -
(setq theVel (objGetVel gSource))
; Remember our weapon range, which is missileSpeed divided by 50.
(setq maxRange (typGetProperty aWeaponType 'range))
;- - - - - - - - - -
; Plot a line of points and spawn a beam at each point. Each point is one light-second apart.
; Very thin targets may be missed completely. That is a minor problem, one not worth fretting over.
; 'i' represents the range each shot will be after they are placed.
;- - - - - - - - - -
(for i 0 maxRange
(if (ls i maxRange)
; YES: Draw beam and hit stuff.
(block (thePos hitList hitScan drawBeam theShotType)
; Project a point where the beam will spawn.
(setq thePos (sysVectorPolarOffset aFirePos aFireAngle i))
; Determine who we can hit at the projected point.
; We scan for all objects that are ships, stations, planetoids, and the like.
; We filter the list to include everyone except the attacker
; because the attacker cannot hit himself and we do not want the
; the attacker to block the beam.
(setq hitList
(filter (sysFindObjectAtPos gSource "st" thePos)
who
(neq who gSource)
)
)
(if hitList
; YES: We hit a ship, station, or similar object, and we want to stop the beam.
; Block the beam by failing the loop condition for the next iteration.
(setq maxRange i)
; NO: We did not hit anything that should block the beam.
; We may have hit nothing, or we may have hit an enemy missile.
)
; Get the first object our beam will expect to hit.
(setq hitScan (@ hitList 0))
;- - - - - - - - - -
; Our visible beam effects are drawn from the center to a point
; about two light-seconds behind the point. Therefore, the first
; two shots we draw should be invisible because we do not want
; a red beam shown sticking out of the rear of our firing point.
; Remaining beams after the second, those at range 2 or greater,
; shot will be visible.
;- - - - - - - - - -
(setq drawBeam (geq i 2))
(if hitScan
; YES: We hit someone!
(setq theshotType
(if drawBeam
; YES: Select visible beam.
&vt912VisibleLaser;
; NO: Select invisible beam.
&vt912HiddenLaser;
)
)
; NO: We do not expect to hit anyone important this frame or tick.
(setq theshotType
;- - - - - - - - - -
; We select a beam that cannot hit anything except other missiles.
; We do this because our beams will last two ticks, and we do not want
; to hit and damage anything significant after this tick. This would
; be important for beams with passthrough, which is beyond the scope of
; this example mod.
;- - - - - - - - - -
(if drawBeam
; YES: Select visible beam.
&vt912FakeVisibleLaser;
; NO: Select invisible beam.
&vt912FakeHiddenLaser;
)
)
)
; Spawn our beam segment here! Our beams hit instantly, and should have zero speed
; on their own. The only velocity our beams should have is the same velocity as the attacker.
(objIncVel
(sysCreateWeaponFire theShotType gSource thePos aFireAngle 0 Nil Nil aWeaponBonus)
theVel
)
)
; NO: Pass.
)
)
; We spawned our beams already to override normal attack. Therefore, return not-Nil.
0
)
</OnFireWeapon>
; Called when we start a new game, after ship select.
<OnGlobalUniverseCreated>
(block (newItem)
; Create our gift.
(setq newItem (itmCreate &it912Hitscan; 1))
; Add the new weapon to ship's cargo hold.
(objAddItem gPlayerShip newItem)
; Install the weapon.
(shpInstallDevice gPlayerShip newItem)
)
</OnGlobalUniverseCreated>
</Events>
</ItemType>
</TranscendenceExtension>