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>