Step 1: Create a file called hackgun.cs in your weapons folder and place this code in it: //-------------------------------------------------------------------------- // Hack Gun // can be used by engineer armor type // Credit to BG9 //-------------------------------------------------------------------------- // Sounds //datablock AudioProfile(HackGunActivateSound) //{ // filename = "fx/packs/packs.repairPackOn.wav"; // description = AudioClosest3d; // preload = true; //}; datablock AudioProfile(HackGunFireSound) { filename = "fx/misc/downloading.wav"; //filename = "fx/packs/repair_use.wav"; description = CloseLooping3d; preload = true; }; //-------------------------------------------------------------------------- // Projectile datablock RepairProjectileData(DefaultHackBeam) { sound = ElfFireWetSound; beamRange = 10; beamWidth = 0.15; numSegments = 20; texRepeat = 0.20; blurFreq = 10.0; blurLifetime = 1.0; cutoffAngle = 25.0; textures[0] = "special/bluespark"; textures[1] = "special/BlueImpact"; }; //------------------------------------------------------------------------- // shapebase datablocks datablock ItemData(HackGun) { className = Weapon; catagory = "Spawn Items"; shapeFile = "pack_upgrade_repair.dts"; image = HackGunImage; mass = 1; elasticity = 0.2; friction = 0.6; pickupRadius = 2; rotate = true; pickUpName = "a hack gun"; lightOnlyStatic = true; lightType = "PulsingLight"; lightColor = "0 5 4"; lightTime = 1200; lightRadius = 4; //computeCRC = true; emap = true; }; //-------------------------------------------------------------------------- // Hack Gun datablock ShapeBaseImageData(HackGunImage) { shapeFile = "weapon_repair.dts"; offset = "0 0 0"; item = HackGun; usesEnergy = true; minEnergy = 3; cutOffEnergy = 3.1; emap = true; stateName[0] = "Activate"; stateTransitionOnTimeout[0] = "ActivateReady"; stateTimeoutValue[0] = 0.25; stateName[1] = "ActivateReady"; stateScript[1] = "onActivateReady"; stateSpinThread[1] = Stop; stateTransitionOnAmmo[1] = "Ready"; stateTransitionOnNoAmmo[1] = "ActivateReady"; stateName[2] = "Ready"; stateSpinThread[2] = Stop; stateTransitionOnNoAmmo[2] = "Deactivate"; stateTransitionOnTriggerDown[2] = "Validate"; stateName[3] = "Validate"; stateTransitionOnTimeout[3] = "Validate"; stateTimeoutValue[3] = 0.2; stateEnergyDrain[3] = 3; stateSpinThread[3] = SpinUp; stateScript[3] = "onValidate"; stateIgnoreLoadedForReady[3] = true; stateTransitionOnLoaded[3] = "Hack"; stateTransitionOnNoAmmo[3] = "Deactivate"; stateTransitionOnTriggerUp[3] = "Deactivate"; stateName[4] = "Hack"; stateSound[4] = HackGunFireSound; stateScript[4] = "onHack"; stateSpinThread[4] = FullSpeed; stateAllowImageChange[4] = false; stateSequence[4] = "activate"; stateFire[4] = true; stateEnergyDrain[4] = 16; stateTimeoutValue[4] = 0.2; stateTransitionOnTimeOut[4] = "Hack"; stateTransitionOnNoAmmo[4] = "Deactivate"; stateTransitionOnTriggerUp[4] = "Deactivate"; stateTransitionOnNotLoaded[4] = "Validate"; stateName[5] = "Deactivate"; stateScript[5] = "onDeactivate"; stateSpinThread[5] = SpinDown; stateSequence[5] = "activate"; stateDirection[5] = false; stateTimeoutValue[5] = 0.2; stateTransitionOnTimeout[5] = "ActivateReady"; }; function HackGunImage::onHack(%this,%obj,%slot) { // this = hackgunimage datablock // obj = player wielding the hack gun // slot = weapon slot if(%obj.getEnergyLevel() <= %this.cutOffEnergy) { if(%obj.Hacking > 0) stopHacking(%obj); return; } // reset the flag that indicates an error message has been sent %obj.errMsgSent = false; %target = %obj.Hacking; if(!%target) { // no target -- whoops! never mind echo("no target - stop hacking"); stopHacking(%obj); return; } %hGun = %obj.getMountedImage(%slot); // muzVec is the vector coming from the hack gun's "muzzle" %muzVec = %obj.getMuzzleVector(%slot); // muzNVec = normalized muzVec %muzNVec = VectorNormalize(%muzVec); %hackRange = DefaultHackBeam.beamRange; // scale muzNVec to the range the repair beam can reach %muzScaled = VectorScale(%muzNVec, %hackRange); // muzPoint = the actual point of the gun's "muzzle" %muzPoint = %obj.getMuzzlePoint(%slot); // rangeEnd = muzzle point + length of beam %rangeEnd = VectorAdd(%muzPoint, %muzScaled); // search for just about anything that can be damaged as well as interiors %searchMasks = $TypeMasks::VehicleObjectType | $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType | $TypeMasks::InteriorObjectType; // search for objects within the beam's range that fit the masks above %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); // screen out interiors if(%scanTarg && !(%scanTarg.getType() & $TypeMasks::InteriorObjectType) && !(%scanTarg.getDataBlock().getName() $= "StationVehicle")) { // a target in range was found %hTgt = firstWord(%scanTarg); // is the prospective target an enemies? if(%hTgt.team != %obj.team) // $$ change to != when done testing { // yes, were hacking if(%hTgt != %obj.Hacking) { echo("hack target changed mid-hack!"); stopHacking(%obj); %obj.Hacking = %hTgt; startHacking(%obj); } else { %obj.HackTime = %obj.HackTime - 5000; %failure = (0.1 + (10 - %obj.getEnergyLevel()) / 100); if(getRandom() < %failure) // hack failure { messageClient(%obj.client, 'MsgHackGunFailed', '\c2Hack Failed!~wfx/powered/nexus_deny.wav', %hTgt); echo("hack failed."); stopHacking(%obj); } if(%obj.HackTime < 0) // we have a hack! { if(%hTgt.getGameName() !$= "") %hName = %hTgt.getGameName(); else %hName = %hTgt.getDatablock().getName(); echo("hack success - stop hacking"); stopHacking(%obj); if(Game.SCORE_PER_ITEM_HACK) { Game.awardScoreHack(%obj.client); } if(%hTgt.Hacked) // We are reversing a hack here { messageClient(%obj.client, 'MsgHackGunGotHackRev', '\c4You have reversed the hack your team\'s %1! (%2 points)~wfx/misc/switch_taken.wav', %hName, Game.SCORE_PER_ITEM_HACK); messageTeamExcept(%obj.client, 'MsgHackGunGotTeamHackRev', '\c4Your teammate %1 reversed the hack on your team\'s %3!~wfx/misc/switch_taken.wav', %obj.client.name, $TeamName[%hTgt.team], %hName); endHack(%hTgt); } else { messageClient(%obj.client, 'MsgHackGunGotHack', '\c4You hacked into the %1 Team\'s %2! (%3 points)~wfx/misc/switch_taken.wav', $TeamName[%hTgt.team], %hName, Game.SCORE_PER_ITEM_HACK); messageTeamExcept(%obj.client, 'MsgHackGunGotTeamHack', '\c4Your teammate %1 hacked into the %2 Team\'s %3!~wfx/misc/switch_taken.wav', %obj.client.name, $TeamName[%hTgt.team], %hName); messageTeam(%hTgt.team, 'MsgHackGunGotTeamHack', '\c4Your team\'s %2 was hacked by %1!~wfx/misc/switch_taken.wav', %obj.client.name, %hName); %hTgt.OldOwner = %hTgt.owner; %hTgt.owner = %obj; %hTgt.Hacked = true; %hTgt.OldTeam = %hTgt.team; %hTgt.team = %obj.team; setTargetSensorGroup(%hTgt.getTarget(), %hTgt.team); %hackDuration = 180000 + (getRandom() * 120000); schedule(%hackDuration, Game, "endHack", %hTgt); } } } } else { // its on my team! stopHacking(%obj); } } else { // there is no target in range stopHacking(%obj); } } function HackGunImage::onActivate(%this,%obj,%slot) { echo("snoo - onActivate"); } function endHack(%target) { if(!%target.Hacked) return; %target.team = %target.OldTeam; setTargetSensorGroup(%target.getTarget(), %target.team); %target.owner = %target.OldOwner; %target.Hacked = false; echo("hack has worn off of " @ %target); } function HackGunImage::onDeactivate(%this,%obj,%slot) { %obj.setImageTrigger(%slot, false); if(%obj.Hacking > 0) { stopHacking(%obj); messageClient(%player.client, 'MsgHackGunStopped', '\c2Hacking Stopped.', %hTgt); } %obj.errMsgSent = false; } function HackGunImage::onValidate(%this,%obj,%slot) { %hGun = %obj.getMountedImage(%slot); // muzVec is the vector coming from the hack gun's "muzzle" %muzVec = %obj.getMuzzleVector(%slot); // muzNVec = normalized muzVec %muzNVec = VectorNormalize(%muzVec); %hackRange = DefaultHackBeam.beamRange; // scale muzNVec to the range the repair beam can reach %muzScaled = VectorScale(%muzNVec, %hackRange); // muzPoint = the actual point of the gun's "muzzle" %muzPoint = %obj.getMuzzlePoint(%slot); // rangeEnd = muzzle point + length of beam %rangeEnd = VectorAdd(%muzPoint, %muzScaled); // search for just about anything that can be damaged as well as interiors %searchMasks = $TypeMasks::VehicleObjectType | $TypeMasks::StationObjectType | $TypeMasks::GeneratorObjectType | $TypeMasks::SensorObjectType | $TypeMasks::TurretObjectType | $TypeMasks::InteriorObjectType; // search for objects within the beam's range that fit the masks above %scanTarg = ContainerRayCast(%muzPoint, %rangeEnd, %searchMasks, %obj); // screen out interiors if(%scanTarg && !(%scanTarg.getType() & $TypeMasks::InteriorObjectType)) { // a target in range was found %hTgt = firstWord(%scanTarg); // is the prospective target an enemies? if(%hTgt.team != %obj.team) // $$ change to != when done testing { // yes, it's hackable if(%hTgt != %obj.Hacking) { if(isObject(%obj.Hacking)) stopHacking(%obj); %obj.Hacking = %hTgt; startHacking(%obj); } // setting imageLoaded to true sends us to hack state (function onHack) %obj.setImageLoaded(%slot, true); } else { //echo("team targ: " @ %hTgt.team @ " obj: " @ %obj.team); // there is a target in range, but it's on our team if(!%obj.errMsgSent && !%hTgt.Hacked) //if its hacked by my team, leave it alone { // if the target isn't damaged, send a message to that effect only once messageClient(%obj.client, 'MsgHackGunSameTeam', '\c2No need to hack that!', %hTgt); %obj.errMsgSent = true; } // if player was hacking something, stop the hacking -- we're done if(%obj.Hacking > 0) stopHacking(%obj); } } else { // there is no target in range if(!%obj.errMsgSent) { // send an error message only once messageClient(%obj.client, 'MsgHackGunNoTarget', '\c2No target to hack.'); %obj.errMsgSent = true; } } } function HackGunImage::onActivateReady(%this,%obj,%slot) { %obj.errMsgSent = false; //%obj.Hacking = 0; //%obj.setImageLoaded(%slot, false); //echo("snoo - onActivateReady"); } function HackGunImage::onMount(%this,%obj,%slot) { %obj.errMsgSent = false; %obj.client.setWeaponsHudActive(%this.item); } function stopHacking(%player) { // %player = the player who was using the hack gun if(%player.Hacking > 0) { if(isObject(%player.hackProjectile)) %player.hackProjectile.delete(); } %player.hackProjectile = 0; %player.Hacking = 0; %player.hackTime = 0; %player.errMsgSent = true; %player.setImageTrigger($WeaponSlot, false); %player.setImageLoaded($WeaponSlot, false); } function startHacking(%player) { // %player = the player who was using the hack gun echo("hacking has commenced!"); %initialDirection = %player.getMuzzleVector($WeaponSlot); %initialPosition = %player.getMuzzlePoint($WeaponSlot); %hackTime = 150000; %player.hackTime = %hackTime; %player.hackProjectile = new RepairProjectile() { dataBlock = DefaultHackBeam; initialDirection = %initialDirection; initialPosition = %initialPosition; sourceObject = %player; sourceSlot = $WeaponSlot; targetObject = %player.Hacking; }; MissionCleanup.add(%player.hackProjectile); %hTgt = %player.Hacking; if(%hTgt.getGameName() !$= "") %hName = %hTgt.getGameName(); else %hName = %hTgt.getDatablock().getName(); messageClient(%player.client, 'MsgHackGunStarted', '\c2Hacking %1.', %hName); } function HackGun::onPickup(%this, %obj, %shape, %amount) { // created to prevent console errors } Step 2: Open inventoryHud.cs and add these lines: $InvWeapon[10] = "Hackgun"; //Change Number To Correspond $NameToInv["Hackgun"] = "HackGun"; Step 3: Open weapons.cs and add these lines: $WeaponsHudData[11, bitmapName] = "gui/hud_shocklance"; $WeaponsHudData[11, itemDataName] = "HackGun"; //$WeaponsHudData[11, ammoDataName] = ""; $WeaponsHudData[11, reticle] = "gui/hud_ret_shocklance"; $WeaponsHudData[11, visible] = "false"; And change this "$WeaponsHudCount = 11;" TO: $WeaponsHudCount = 12; //Change number to one number above...I.E 11 then its 12 and so on. Still in weapons.cs right under "exec("scripts/weapons/blaster.cs");" add this: exec("scripts/weapons/hackgun.cs"); Step 4: Still in inventory.cs find this function: function ShapeBase::clearInventory(%this) Find this in that function: %this.setInventory(ShockLance, 0); and right below it add this: %this.setInventory(HackGun, 0); Step 5: Still in inventory.cs find this function: function serverCmdGiveAll(%client) Find this in that function: %player.setInventory(TargetingLaser, 1); and add this right below it: %player.setInventory(HackGun, 1); Step 6: Open player.cs and add your weapon to the armors who can use it: max[HackGun] = 0; //Armor cannot use weapon max[HackGun] = 1; //Armor can use weapon