construction-mod/scripts/weapons/constructionTool.cs

1169 lines
43 KiB
C#
Raw Normal View History

2025-06-05 10:37:16 +00:00
//--------------------------------------------------------------------------
// Deconstruct Gun / Construction Tool
// Originally from Hammer Mod. Changed and redone for LuCiD MoD.
// Also Changed again and redone for Construction Mod.
// All changes made by LuCiD from LuCiD MoD & Mostlikely or JackTL from Construction Mod.
$ReverseDeployItem[DeployedStationInventory] = InventoryDeployable;
$ReverseDeployItem[DeployedMotionSensor] = MotionSensorDeployable;
$ReverseDeployItem[DeployedPulseSensor] = PulseSensorDeployable;
$ReverseDeployItem[TurretDeployedOutdoor] = TurretOutdoorDeployable;
$ReverseDeployItem[TurretDeployedFloorIndoor] = TurretIndoorDeployable;
$ReverseDeployItem[TurretDeployedWallIndoor] = TurretIndoorDeployable;
$ReverseDeployItem[TurretDeployedCeilingIndoor] = TurretIndoorDeployable;
$ReverseDeployItem[TurretDeployedBase] = TurretBasePack;
$ReverseDeployItem[TurretDeployedCamera] = CameraGrenade;
$ReverseDeployItem[TelePadDeployedBase] = TelePadPack;
$ReverseDeployItem[DeployedSpine] = "poof spineDeployable";
$ReverseDeployItem[DeployedWoodSpine] = "poof spineDeployable";
$ReverseDeployItem[Deployedfloor] = "poof floorDeployable";
$ReverseDeployItem[Deployedwall] = "poof wallDeployable";
$ReverseDeployItem[Deployedwwall] = "poof wwallDeployable";
$ReverseDeployItem[Deployedmspine] = "poof mspineDeployable";
$ReverseDeployItem[DeployedDoor] = "poof DoorDeployable";
$ReverseDeployItem[DeployedEnergizer] = EnergizerDeployable;
$ReverseDeployItem[Deployedmspinering] = "poof nothing";
$ReverseDeployItem[DiscTurretDeployed] = DiscTurretDeployable;
$ReverseDeployItem[StationInventory] = LargeInventoryDeployable;
$ReverseDeployItem[DeployedJumpad] = JumpadDeployable;
$ReverseDeployItemDeployedBeacon = Beacon;
$ReverseDeployItem[DeployedLogoProjector] = LogoProjectorDeployable;
$ReverseDeployItem[LaserDeployed] = TurretLaserDeployable;
$ReverseDeployItem[MissileRackTurretDeployed] = TurretMissileRackDeployable;
$ReverseDeployItem[SensorMediumPulse] = MediumSensorDeployable;
$ReverseDeployItem[SensorLargePulse] = LargeSensorDeployable;
$ReverseDeployItem[DeployedLightBase] = "LightDeployable";
$ReverseDeployItem[DeployedTripwire] = "TripwireDeployable";
$ReverseDeployItem[DeployedEscapePod] = "EscapePodDeployable";
//Note this can also be in "pack".cs
//[most]
$ReverseDeployItem[Mpm_Anti_TurretDeployed] = "TurretMpm_Anti_Deployable";
$ReverseDeployItem[DeployableVehiclePadBottom] = "VehiclePadPack";
$ReverseDeployItem[DeployableVehiclePad] = "VehiclePadPack";
$ReverseDeployItem[DeployableVehicleStation] = "VehiclePadPack";
$ReverseDeployItem[DeployableVehiclePad2] = "VehiclePadPack";
$ReverseDeployItem[PotPipe] = "poof";
$ReverseDeployItem[EmitterDep] = "poof EmitterDepPack";
$ReverseDeployItem[AudioDep] = "poof AudioDepPack";
$ReverseDeployItem[DispenserDep] = "poof DispenserDepPack";
$ReverseDeployItem[Mpm_Beacon_Ghost] = "poof";
$ReverseDeployItem[DetonationDep] = "DetonationDepPack";
$ReverseDeployItem[DetonationDepArm] = "DetonationDepPack";
//[most]
for (%i = 0;%i < 21;%i++)
$ReverseDeployItemDeployedForcefield[%i] = "ForceFieldDeployable";
for (%i = 0;%i < 5;%i++)
$ReverseDeployItemDeployedGravityField[%i] = "GravityFieldDeployable";
for (%i = 0;%i < 14;%i++)
$ReverseDeployItemDeployedTree[%i] = "TreeDeployable";
for (%i = 0;%i < 13;%i++)
$ReverseDeployItemDeployedCrate[%i] = "CrateDeployable";
for (%i = 0;%i < 16;%i++)
$ReverseDeployItemDeployedDecoration[%i] = "DecorationDeployable";
// power
$ReverseDeployItem[GeneratorLarge] = GeneratorDeployable;
$ReverseDeployItem[SolarPanel] = SolarPanelDeployable;
$ReverseDeployItem[DeployedSwitch] = SwitchDeployable;
// DeconTarget
$ReverseDeployItem[DeployedLTarget] = "poof";
//--------------------------------------------------------------------------
// Sounds
datablock EffectProfile(ConstructionToolSwitchEffect) {
effectname = "packs/packs.repairPackOn";
minDistance = 2.5;
maxDistance = 2.5;
};
datablock EffectProfile(ConstructionToolFireEffect) {
effectname = "misc/downloading";
minDistance = 2.5;
maxDistance = 5.0;
};
datablock AudioProfile(ConstructionToolSwitchSound) {
filename = "fx/packs/packs.repairPackOn.wav";
description = AudioClosest3d;
preload = true;
effect = ConstructionToolSwitchEffect;
};
datablock AudioProfile(ConstructionToolFireSound) {
filename = "fx/misc/downloading.wav";
description = CloseLooping3d;
preload = true;
effect = ConstructionToolFireEffect;
};
//--------------------------------------------------------------------------
// Projectile
datablock RepairProjectileData(ConstructionToolBeam) {
sound = ElfFireWetSound;
beamRange = 100;
beamWidth = 0.15;
numSegments = 20;
texRepeat = 0.20;
blurFreq = 10.0;
blurLifetime = 1.0;
cutoffAngle = 25.0;
textures[0] = "special/ELFLightning";
textures[1] = "skins/flaregreen";
};
//-------------------------------------------------------------------------
// shapebase datablocks
datablock ItemData(ConstructionTool) {
className = Weapon;
catagory = "Spawn Items";
shapeFile = "weapon_shocklance.dts";
image = ConstructionToolImage;
mass = 1;
elasticity = 0.2;
friction = 0.6;
pickupRadius = 2;
rotate = true;
pickUpName = "a construction tool";
lightOnlyStatic = true;
lightType = "PulsingLight";
lightColor = "0 1 0 1";
lightTime = 1200;
lightRadius = 4;
//computeCRC = true;
emap = true;
};
//--------------------------------------------------------------------------
// Construction Tool
datablock ShapeBaseImageData(ConstructionToolImage) {
shapeFile = "weapon_shocklance.dts";
offset = "0 0 0";
item = ConstructionTool;
usesEnergy = true;
minEnergy = 3;
cutOffEnergy = 3.1;
emap = true;
stateName[0] = "Activate";
stateTransitionOnTimeout[0] = "ActivateReady";
stateTimeoutValue[0] = 0.25;
stateSound[0] = ConstructionToolSwitchSound;
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] = "PerformAction";
stateTransitionOnNoAmmo[3] = "Deactivate";
stateTransitionOnTriggerUp[3] = "Deactivate";
stateName[4] = "PerformAction";
stateSound[4] = ConstructionToolFireSound;
stateScript[4] = "onPerformAction";
stateSpinThread[4] = FullSpeed;
stateAllowImageChange[4] = false;
stateSequence[4] = "activate";
stateFire[4] = true;
stateEnergyDrain[4] = 16;
stateTimeoutValue[4] = 0.2;
stateTransitionOnTimeOut[4] = "PerformAction";
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 ConstructionToolImage::onActivate(%this,%obj,%slot) {
}
function ConstructionToolImage::onActivateReady(%this,%obj,%slot) {
%obj.errMsgSent = false;
}
function ConstructionToolImage::onValidate(%this,%obj,%slot) {
switch (%obj.constructionToolMode) {
case 0: // disassemble
onValidateDisassemble(%this,%obj,%slot);
case 1: // rotate
onValidateRotate(%this,%obj,%slot);
case 2: // advanced rotate
onValidateAdvancedRotate(%this,%obj,%slot);
case 3: // power management
onValidatePowerManagement(%this,%obj,%slot);
}
}
function ConstructionToolImage::onPerformAction(%this,%obj,%slot) {
// this = ConstructionToolImage datablock
// obj = player wielding the construction tool
// slot = weapon slot
if (%obj.getEnergyLevel() <= %this.cutOffEnergy) {
if (%obj.performing > 0)
stopPerforming(%obj);
return;
}
// reset the flag that indicates an error message has been sent
%obj.errMsgSent = false;
switch (%obj.constructionToolMode) {
case 0: // disassemble
onPerformDisassemble(%this,%obj,%slot);
case 1: // rotate
onPerformRotate(%this,%obj,%slot);
case 2: // advanced rotate
onPerformAdvancedRotate(%this,%obj,%slot);
case 3: // power management
onPerformPowerManagement(%this,%obj,%slot);
}
}
function ConstructionToolImage::onDeactivate(%this,%obj,%slot) {
%obj.setImageTrigger(%slot, false);
if (%obj.performing > 0) {
stopPerforming(%obj);
messageClient(%player.client, 'msgClient', '\c2Construction Tool stopped.');
}
%obj.errMsgSent = false;
}
function ConstructionToolImage::onMount(%this,%obj,%slot) {
if (!$Host::TournamentMode) {
%curWeap = ( %obj.getMountedImage($WeaponSlot) == 0 ) ? "" : %obj.getMountedImage($WeaponSlot).getName().item.pickUpName;
BottomPrint(%obj.client, "Now using " @ %curWeap, 2, 1 );
}
%obj.errMsgSent = false;
%obj.client.setWeaponsHudActive(%this.item);
%obj.usingConstructionTool = true;
if (!%obj.constructionToolMode)
%obj.constructionToolMode = 0;
if (!%obj.constructionToolMode2)
%obj.constructionToolMode2 = 0;
WeaponImage::onMount(%this,%obj,%slot);
}
function ConstructionToolImage::onUnmount(%data, %obj, %slot) {
%obj.usingConstructionTool = false;
%obj.setImageTrigger(%slot, false);
if (%obj.performing > 0) {
stopPerforming(%obj);
messageClient(%player.client, 'msgClient', '\c2Construction Tool stopped.');
}
%obj.errMsgSent = false;
Parent::deconstruct(%data, %obj, %slot);
WeaponImage::onUnmount(%data, %obj, %slot);
}
function ConstructionTool::onPickup(%this, %obj, %shape, %amount) {
// created to prevent console errors
}
// --------------------------------------------------------------------------------
// Common functions
// --------------------------------------------------------------------------------
function startPerforming(%player) {
// %player = the player who was using the construction tool
%initialDirection = %player.getMuzzleVector($WeaponSlot);
%initialPosition = %player.getMuzzlePoint($WeaponSlot);
//else
%performTime = 250;
%player.performTime = %performTime;
// Temporary (hopefully) fix
%data = %player.performing.getDataBlock();
%dataBlockName = %data.getName();
if (%data.className !$= "forcefield" && %data.className !$= "gravityfield") {
%player.constructionToolProjectile = new RepairProjectile() {
dataBlock = ConstructionToolBeam;
initialDirection = %initialDirection;
initialPosition = %initialPosition;
sourceObject = %player;
sourceSlot = $WeaponSlot;
targetObject = %player.performing;
};
MissionCleanup.add(%player.constructionToolProjectile);
}
%hTgt = %player.performing;
%hTgt.beingPerformed = true;
}
function stopPerforming(%player) {
// %player = the player who was using the construction tool
if (%player.performing > 0) {
if (isObject(%player.constructionToolProjectile))
%player.constructionToolProjectile.delete();
}
%hTgt.beingPerformed = false;
%player.constructionToolProjectile = 0;
%player.performing = 0;
%player.performTime = 0;
%player.errMsgSent = true;
%player.setImageTrigger($WeaponSlot, false);
%player.setImageLoaded($WeaponSlot, false);
%client = %player.client;
if (%client.CampingThread)
cancel(%client.campingThread);
return;
}
// --------------------------------------------------------------------------------
// Disassemble functions
// --------------------------------------------------------------------------------
function onValidateDisassemble(%this,%obj,%slot) {
%hGun = %obj.getMountedImage(%slot);
// muzVec is the vector coming from the construction tool's "muzzle"
%muzVec = %obj.getMuzzleVector(%slot);
// muzNVec = normalized muzVec
%muzNVec = VectorNormalize(%muzVec);
%beamRange = ConstructionToolBeam.beamRange;
// scale muzNVec to the range the repair beam can reach
%muzScaled = VectorScale(%muzNVec, %beamRange);
// 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::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType;
// 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);
// can it be dissed? is it already being tooled?
if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed)
%canPerform = true;
// Only deconstruct deployed items, not base ones
%dataBlockName = %hTgt.getDataBlock().getName();
if (%canPerform == true && (
%dataBlockName $= "StationInventory" ||
%dataBlockName $= "GeneratorLarge" ||
%dataBlockName $= "SolarPanel" ||
%dataBlockName $= "SensorMediumPulse" ||
%dataBlockName $= "SensorLargePulse"
))
if (%hTgt.deployed != true)
%canPerform = false;
if (%canPerform == true) {
// yes, it's disassembleable
if (%hTgt != %obj.performing) {
if (isObject(%obj.performing))
stopPerforming(%obj);
%obj.performing = %hTgt;
startPerforming(%obj);
}
// setting imageLoaded to true sends us to deconstruct state (function onPerformAction)
%obj.setImageLoaded(%slot, true);
}
else {
// there is a target in range, but it's not disable
if (!%obj.errMsgSent) {
messageClient(%obj.client, 'msgClient', '\c2You can\'t deconstruct that.');
%obj.errMsgSent = true;
}
// if player was Disassembling something, stop the disassembling -- we're done
if (%obj.performing > 0)
stopPerforming(%obj);
}
}
else {
// there is no target in range
if (!%obj.errMsgSent) {
// send an error message only once
messageClient(%obj.client, 'msgClient', '\c2No target to deconstruct.');
%obj.errMsgSent = true;
}
}
}
function onPerformDisassemble(%this,%obj,%slot) {
%target = %obj.performing;
if (!%target) {
// no target -- whoops! never mind
stopPerforming(%obj);
return;
}
if (%obj.constructionToolMode2 == 0)
%cascade = 0;
else
%cascade = 1;
%hGun = %obj.getMountedImage(%slot);
// muzVec is the vector coming from the construction tool's "muzzle"
%muzVec = %obj.getMuzzleVector(%slot);
// muzNVec = normalized muzVec
%muzNVec = VectorNormalize(%muzVec);
%beamRange = ConstructionToolBeam.beamRange;
// scale muzNVec to the range the repair beam can reach
%muzScaled = VectorScale(%muzNVec, %beamRange);
// 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::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType;
// 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);
// can it be dissed? is it already being tooled?
if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed)
%canPerform = true;
// Only deconstruct deployed items, not base ones
%dataBlockName = %hTgt.getDataBlock().getName();
if (%canPerform == true && (
%dataBlockName $= "StationInventory" ||
%dataBlockName $= "GeneratorLarge" ||
%dataBlockName $= "SolarPanel" ||
%dataBlockName $= "SensorMediumPulse" ||
%dataBlockName $= "SensorLargePulse"
))
if (%hTgt.deployed != true)
%canPerform = false;
if (%canPerform == true) {
// yes, it's disassembleable
if (%hTgt != %obj.performing) { // its not what we were originally dising
if (isObject(%obj.performing)) {
stopPerforming(%obj);
%obj.performing = %hTgt;
startPerforming(%obj);
}
}
else { // continue dising
%obj.performTime = %obj.performTime - 120;
if (%obj.performTime < 0) { // we have a dis!
if (%hTgt.isRemoved)
return; // Avoid duplicate disassemblies
if (%hTgt.team != %obj.team && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) {
messageClient(%obj.client, 'msgClient', '\c2Deconstruction failed! Wrong team!~wfx/powered/nexus_deny.wav');
stopPerforming(%obj);
return;
}
if ($Host::OnlyOwnerDeconstruct == 1 && %hTgt.getOwner() != %obj.client && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) {
if (isObject(%hTgt.getOwner()))
messageClient(%obj.client, 'msgClient', '\c2Deconstruction failed! This belongs to %1!~wfx/powered/nexus_deny.wav', %hTgt.getOwner().nameBase);
else
messageClient(%obj.client, 'msgClient', '\c2Deconstruction failed! Not your stuff!~wfx/powered/nexus_deny.wav');
stopPerforming(%obj);
return;
}
stopPerforming(%obj);
if (%cascade && $Host::OnlyOwnerCascade == 1 && %hTgt.getOwner() != %obj.client && !(%obj.client.isAdmin || %obj.client.isSuperAdmin))
messageClient(%obj.client, 'msgClient', '\c2Cascade failed! Not your stuff!~wfx/powered/nexus_deny.wav');
else {
if ((%hTgt.getType() & $TypeMasks::StaticShapeObjectType) && %hTgt.getDamageLeftPct() < (0.25 + ((getRandom() * 0.2) - 0.1))) {
if ($Host::InvincibleDeployables == 1 && %hTgt.getDamageLeftPct() <= 0) {
// %hTgt.setDamageLevel(%hTgt.getDataBlock().maxDamage - 0.01);
%hTgt.setDamageLevel(0); // Make sure we can blow it up..
}
%hTgt.damageFailedDecon = true;
%hTgt.schedule(100,setDamageState,Destroyed);
messageClient(%obj.client, 'msgClient', '\c2Deconstruction failed!~wfx/powered/nexus_deny.wav');
}
else {
%hTgt.getDataBlock().disassemble(%obj, %hTgt); // Run Item Specific code.
if (%cascade)
cascade(%hTgt,true);
if (%hTgt.getDataBlock().getName() $= "DeployedLTarget" && isObject(%hTgt.lMain))
%revItem = %hTgt.lMain.getDataBlock().getName();
else
%revItem = %hTgt.getDataBlock().getName();
%newPack = $ReverseDeployItem[%revItem];
if (getWord(%newPack,0) !$= "poof") {
%npack = new Item() {
dataBlock = %newPack;
};
MissionCleanup.add(%npack);
%npack.schedulePop();
if (%newPack $= "ForceFieldDeployable" || %newPack $= "GravityFieldDeployable" || %newPack $= "DecorationDeployable")
%pos = %hTgt.getWorldBoxCenter();
else
%pos = %hTgt.getPosition();
%npack.setTransform(getWords(%scanTarg,1,3) SPC "0 0 1" SPC (getRandom() * ($Pi * 2)));
}
}
}
}
}
}
}
else
stopPerforming(%obj);
}
// --------------------------------------------------------------------------------
// Rotate functions
// --------------------------------------------------------------------------------
function onValidateRotate(%this,%obj,%slot) {
%hGun = %obj.getMountedImage(%slot);
// muzVec is the vector coming from the construction tool's "muzzle"
%muzVec = %obj.getMuzzleVector(%slot);
// muzNVec = normalized muzVec
%muzNVec = VectorNormalize(%muzVec);
%beamRange = ConstructionToolBeam.beamRange;
// scale muzNVec to the range the repair beam can reach
%muzScaled = VectorScale(%muzNVec, %beamRange);
// 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::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType;
// 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);
// can it be rotated? is it already being tooled?
if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed)
%canPerform = true;
// Only rotate deployed items, not base ones
%dataBlockName = %hTgt.getDataBlock().getName();
if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain))
%canPerform = false;
if (%canPerform == true && (
%dataBlockName $= "StationInventory" ||
%dataBlockName $= "GeneratorLarge" ||
%dataBlockName $= "SolarPanel" ||
%dataBlockName $= "SensorMediumPulse" ||
%dataBlockName $= "SensorLargePulse"
))
if (%hTgt.deployed != true)
%canPerform = false;
if (%canPerform == true) {
// yes, it's rotatable
if (%hTgt != %obj.performing) {
if (isObject(%obj.performing))
stopPerforming(%obj);
%obj.performing = %hTgt;
startPerforming(%obj);
}
// setting imageLoaded to true sends us to rotate state (function onPerformAction)
%obj.setImageLoaded(%slot, true);
}
else {
// there is a target in range, but it's not rotatable
if (!%obj.errMsgSent) {
messageClient(%obj.client, 'msgClient', '\c2You can\'t rotate that.');
%obj.errMsgSent = true;
}
// if player was rotating something, stop the rotating -- we're done
if (%obj.performing > 0)
stopPerforming(%obj);
}
}
else {
// there is no target in range
if (!%obj.errMsgSent) {
// send an error message only once
messageClient(%obj.client, 'msgClient', '\c2No target to rotate.');
%obj.errMsgSent = true;
}
}
}
function onPerformRotate(%this,%obj,%slot) {
%target = %obj.performing;
if (!%target) {
// no target -- whoops! never mind
stopPerforming(%obj);
return;
}
if (%obj.constructionToolMode2 == 0)
%rotVal = 1;
else
%rotVal = -1;
%hGun = %obj.getMountedImage(%slot);
// muzVec is the vector coming from the construction tool's "muzzle"
%muzVec = %obj.getMuzzleVector(%slot);
// muzNVec = normalized muzVec
%muzNVec = VectorNormalize(%muzVec);
%beamRange = ConstructionToolBeam.beamRange;
// scale muzNVec to the range the repair beam can reach
%muzScaled = VectorScale(%muzNVec, %beamRange);
// 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::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType;
// 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);
// can it be rotated? is it already being tooled?
if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed)
%canPerform = true;
// Only rotate deployed items, not base ones
%dataBlockName = %hTgt.getDataBlock().getName();
if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain))
%canPerform = false;
if (%canPerform == true && (
%dataBlockName $= "StationInventory" ||
%dataBlockName $= "GeneratorLarge" ||
%dataBlockName $= "SolarPanel" ||
%dataBlockName $= "SensorMediumPulse" ||
%dataBlockName $= "SensorLargePulse"
))
if (%hTgt.deployed != true)
%canPerform = false;
if (%canPerform == true) {
// yes, it's rotatable
if (%hTgt != %obj.performing) { // its not what we were originally rotating
if (isObject(%obj.performing)) {
stopPerforming(%obj);
%obj.performing = %hTgt;
startPerforming(%obj);
}
}
else { // continue rotating
%obj.performTime = %obj.performTime - 120;
if (%obj.performTime < 0) { // we have a rot!
if (%hTgt.team != %obj.team && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) {
messageClient(%obj.client, 'msgClient', '\c2Rotate failed! Wrong team!~wfx/powered/nexus_deny.wav');
stopPerforming(%obj);
return;
}
if ($Host::OnlyOwnerRotate == 1 && %hTgt.getOwner() != %obj.client && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) {
messageClient(%obj.client, 'msgClient', '\c2Rotate failed! Not your stuff!~wfx/powered/nexus_deny.wav');
stopPerforming(%obj);
return;
}
stopPerforming(%obj);
%obj = firstWord(%scanTarg);
%vec1 = posFromRaycast(%scanTarg);
%vec2 = normalFromRaycast(%scanTarg);
pullObject(%obj,%vec1,%vec2,$Pi/8*%rotVal,"0 0 0");
}
}
}
}
else
stopPerforming(%obj);
}
// --------------------------------------------------------------------------------
// Advanced rotate functions
// --------------------------------------------------------------------------------
function onValidateAdvancedRotate(%this,%obj,%slot) {
%m2 = %obj.constructionToolMode2;
if (%m2 == 2 || %m2 == 3 || %m2 == 4 || %m2 == 5) {
%obj.setImageLoaded(%slot, true);
return;
}
%hGun = %obj.getMountedImage(%slot);
// muzVec is the vector coming from the construction tool's "muzzle"
%muzVec = %obj.getMuzzleVector(%slot);
// muzNVec = normalized muzVec
%muzNVec = VectorNormalize(%muzVec);
%beamRange = ConstructionToolBeam.beamRange;
// scale muzNVec to the range the repair beam can reach
%muzScaled = VectorScale(%muzNVec, %beamRange);
// 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::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType;
// 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);
// can it be selected? is it already being tooled?
if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed)
%canPerform = true;
// Only select deployed items, not base ones
%dataBlockName = %hTgt.getDataBlock().getName();
if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain))
%canPerform = false;
if (%canPerform == true && (
%dataBlockName $= "StationInventory" ||
%dataBlockName $= "GeneratorLarge" ||
%dataBlockName $= "SolarPanel" ||
%dataBlockName $= "SensorMediumPulse" ||
%dataBlockName $= "SensorLargePulse"
))
if (%hTgt.deployed != true)
%canPerform = false;
if (!$Host::AllowUnderground) {
if (%dataBlockName $= "TelePadDeployedBase")
%canPerform = false;
}
if (%canPerform == true) {
// yes, it's selectable
if (%hTgt != %obj.performing) {
if (isObject(%obj.performing))
stopPerforming(%obj);
%obj.performing = %hTgt;
startPerforming(%obj);
}
// setting imageLoaded to true sends us to select state (function onPerformAction)
%obj.setImageLoaded(%slot, true);
}
else {
// there is a target in range, but it's not selectable
if (!%obj.errMsgSent) {
messageClient(%obj.client, 'msgClient', '\c2You can\'t select/rotate that.');
%obj.errMsgSent = true;
}
// if player was selecting something, stop the selecting -- we're done
if (%obj.performing > 0)
stopPerforming(%obj);
}
}
else {
// there is no target in range
if (!%obj.errMsgSent) {
// send an error message only once
messageClient(%obj.client, 'msgClient', '\c2No target to select/rotate.');
%obj.errMsgSent = true;
}
}
}
function onPerformAdvancedRotate(%this,%obj,%slot) {
// Account for lag, and make gun a bit less trigger happy
%m2 = %obj.constructionToolMode2;
if (%m2 == 2 || %m2 == 3 || %m2 == 4 || %m2 == 5) {
if (getSimTime() < (%obj.constructionToolTime + 500))
return;
}
else {
if (getSimTime() < (%obj.constructionToolTime + 500) && %obj.performTime < 0)
return;
}
%obj.constructionToolTime = getSimTime();
// Load rotation list
%list = %obj.rotList;
// Validate list
%size = getWordCount(%list);
for(%id = 0; %id < %size; %id++) {
if (!isObject(getWord(%list,%id)))
%badIDs = %badIDs SPC %id;
}
%list = listDel(%list,trim(%badIDs));
if (!%list) // Is there a rotation list?
%list = %obj; // Set player as center.
// Save list
%obj.rotList = %list;
if (%obj.rotSpeed == 0) // So players can rotate without specifically setting rotSpeed
%obj.rotSpeed = 1;
if (%obj.constructionToolMode2 == 2) {
%obj.rotSpeed++;
if (%obj.rotSpeed > 3)
%obj.rotSpeed = -3;
if (%obj.rotSpeed == 0)
%obj.rotSpeed = 1;
%mod = lev(%obj.rotSpeed) * 5 * mPow(3,mAbs(%obj.rotSpeed) -1);
bottomPrint(%obj.client,"Rotation speed set to:" SPC %mod SPC " degrees per tick",2,1);
return;
}
else if(%obj.constructionToolMode2 == 3) {
%angle =lev(%obj.rotSpeed) * 5 * mPow(3,mAbs(%obj.rotSpeed) -1) / 180 * $Pi;
%mod = lev(%obj.rotSpeed) * 5 * mPow(3,mAbs(%obj.rotSpeed) -1);
rotateSection(getWord(%list,0),%list,"0 0 1" SPC %angle);
%obj.constructionToolTime = %obj.constructionToolTime + (getWordCount(%list) * 100);
bottomPrint(%obj.client,getWordCount(%list) SPC "objects rotated" SPC %mod SPC " degrees (wait " @ mFloor((%obj.constructionToolTime - getSimTime()) / 1000) @ " seconds)",2,1);
return;
}
else if(%obj.constructionToolMode2 == 4) {
for(%id = 0; %id < getWordCount(%list); %id++) {
%obj = getWord(%list,%id);
%obj.startFade(400,%id * 100,0);
if (isObject(%obj.lMain))
%obj.lMain.startFade(400,%id * 100,0);
}
bottomPrint(%obj.client,getWordCount(%list) SPC "objects selected including the rotation center",2,1);
return;
}
else if(%obj.constructionToolMode2 == 5) {
%list = "";
%obj.rotList = %list;
bottomPrint(%obj.client,"All objects removed from rotation list - player set as rotation center",2,1);
return;
}
%target = %obj.performing;
if (!%target) {
// no target -- whoops! never mind
stopPerforming(%obj);
return;
}
%hGun = %obj.getMountedImage(%slot);
// muzVec is the vector coming from the construction tool's "muzzle"
%muzVec = %obj.getMuzzleVector(%slot);
// muzNVec = normalized muzVec
%muzNVec = VectorNormalize(%muzVec);
%beamRange = ConstructionToolBeam.beamRange;
// scale muzNVec to the range the repair beam can reach
%muzScaled = VectorScale(%muzNVec, %beamRange);
// 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::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType;
// 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);
// can it be selected? is it already being tooled?
if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed)
%canPerform = true;
// Only select deployed items, not base ones
%dataBlockName = %hTgt.getDataBlock().getName();
if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain))
%canPerform = false;
if (%canPerform == true && (
%dataBlockName $= "StationInventory" ||
%dataBlockName $= "GeneratorLarge" ||
%dataBlockName $= "SolarPanel" ||
%dataBlockName $= "SensorMediumPulse" ||
%dataBlockName $= "SensorLargePulse"
))
if (%hTgt.deployed != true)
%canPerform = false;
if (!$Host::AllowUnderground) {
if (%dataBlockName $= "TelePadDeployedBase")
%canPerform = false;
}
if (%canPerform == true) {
// yes, it's selectable
if (%hTgt != %obj.performing) { // its not what we were originally selecting
if (isObject(%obj.performing)) {
stopPerforming(%obj);
%obj.performing = %hTgt;
startPerforming(%obj);
}
}
else { // continue selecting
%obj.performTime = %obj.performTime - 120;
if (%obj.performTime < 0) { // we have a select!
if (%hTgt.team != %obj.team && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) {
messageClient(%obj.client, 'msgClient', '\c2Select failed! Wrong team!~wfx/powered/nexus_deny.wav');
stopPerforming(%obj);
return;
}
if ($Host::OnlyOwnerRotate == 1 && %hTgt.getOwner() != %obj.client && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) {
messageClient(%obj.client, 'msgClient', '\c2Select failed! Not your stuff!~wfx/powered/nexus_deny.wav');
stopPerforming(%obj);
return;
}
if (%obj.constructionToolMode2 == 0) {
if (%hTgt == getWord(%list,0)) { // Is it already the center?
%list = listReplace(%list,%obj,0); // Replace player as center
bottomPrint(%obj.client,"Object deselected as center",2,1);
}
else {
// Remove it from the list if it was in the list to start with.
%loc = findWord(%list,%hTgt);
if (%loc !$= "")
%list = listDel(%list,%loc);
%list = listReplace(%list,%hTgt,0); // Replace player as center
bottomPrint(%obj.client,"Object selected as center",2,1);
}
%hTgt.startFade(400,%id * 100,0);
if (isObject(%hTgt.lMain))
%hTgt.lMain.startFade(400,%id * 100,0);
}
else if (%obj.constructionToolMode2 == 1) {
if (%hTgt == getWord(%list,0))
bottomPrint(%obj.client,"Object is already center of rotation",2,1);
else {
%loc = findWord(%list,%hTgt);
if (%loc !$= "") { // Is it already in the list?
%list = listDel(%list,%loc);
bottomPrint(%obj.client,"Object deselected",2,1);
}
else {
%tempList = %list;
%list = %tempList SPC %hTgt;
bottomPrint(%obj.client,"Object Selected",2,1);
}
}
%hTgt.startFade(400,%id * 100,0);
if (isObject(%hTgt.lMain))
%hTgt.lMain.startFade(400,%id * 100,0);
}
}
}
}
}
else
stopPerforming(%obj);
%obj.rotList = %list;
}
// --------------------------------------------------------------------------------
// Power management functions
// --------------------------------------------------------------------------------
function onValidatePowerManagement(%this,%obj,%slot) {
%m2 = %obj.constructionToolMode2;
if (%m2 == 1 || %m2 == 2) {
%obj.setImageLoaded(%slot, true);
return;
}
%hGun = %obj.getMountedImage(%slot);
// muzVec is the vector coming from the construction tool's "muzzle"
%muzVec = %obj.getMuzzleVector(%slot);
// muzNVec = normalized muzVec
%muzNVec = VectorNormalize(%muzVec);
%beamRange = ConstructionToolBeam.beamRange;
// scale muzNVec to the range the repair beam can reach
%muzScaled = VectorScale(%muzNVec, %beamRange);
// 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::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType;
// 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);
// can it be used? is it already being tooled?
if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed)
%canPerform = true;
// Only use deployed items, not base ones
%dataBlockName = %hTgt.getDataBlock().getName();
if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain))
%canPerform = false;
if (%canPerform == true && (
%dataBlockName $= "StationInventory" ||
%dataBlockName $= "GeneratorLarge" ||
%dataBlockName $= "SolarPanel" ||
%dataBlockName $= "SensorMediumPulse" ||
%dataBlockName $= "SensorLargePulse"
))
if (%hTgt.deployed != true)
%canPerform = false;
if (%canPerform == true) {
// yes, it's usable
if (%hTgt != %obj.performing) {
if (isObject(%obj.performing))
stopPerforming(%obj);
%obj.performing = %hTgt;
startPerforming(%obj);
}
// setting imageLoaded to true sends us to use state (function onPerformAction)
%obj.setImageLoaded(%slot, true);
}
else {
// there is a target in range, but it's not usable
if (!%obj.errMsgSent) {
messageClient(%obj.client, 'msgClient', '\c2You can\'t use that.');
%obj.errMsgSent = true;
}
// if player was using something, stop it -- we're done
if (%obj.performing > 0)
stopPerforming(%obj);
}
}
else {
// there is no target in range
if (!%obj.errMsgSent) {
// send an error message only once
messageClient(%obj.client, 'msgClient', '\c2No target to use.');
%obj.errMsgSent = true;
}
}
}
function onPerformPowerManagement(%this,%obj,%slot) {
// Account for lag, and make gun a bit less trigger happy
%m2 = %obj.constructionToolMode2;
if (%m2 == 1 || %m2 == 2) {
if (getSimTime() < (%obj.constructionToolTime + 500))
return;
}
else {
if (getSimTime() < (%obj.constructionToolTime + 500) && %obj.performTime < 0)
return;
}
%obj.constructionToolTime = getSimTime();
if (%obj.constructionToolMode2 == 1) {
%obj.powerFreq++;
if (%obj.powerFreq > upperPowerFreq(%obj))
%obj.powerFreq = 1;
displayPowerFreq(%obj);
return;
}
else if (%obj.constructionToolMode2 == 2) {
%obj.powerFreq--;
if (%obj.powerFreq < 1)
%obj.powerFreq = upperPowerFreq(%obj);
displayPowerFreq(%obj);
return;
}
%target = %obj.performing;
if (!%target) {
// no target -- whoops! never mind
stopPerforming(%obj);
return;
}
%hGun = %obj.getMountedImage(%slot);
// muzVec is the vector coming from the construction tool's "muzzle"
%muzVec = %obj.getMuzzleVector(%slot);
// muzNVec = normalized muzVec
%muzNVec = VectorNormalize(%muzVec);
%beamRange = ConstructionToolBeam.beamRange;
// scale muzNVec to the range the repair beam can reach
%muzScaled = VectorScale(%muzNVec, %beamRange);
// 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::InteriorObjectType | $TypeMasks::StaticShapeObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType;
// 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);
// can it be used? is it already being tooled?
if ($ReverseDeployItem[%hTgt.getDataBlock().getName()] !$= "" && !%hTht.beingPerformed)
%canPerform = true;
// Only use deployed items, not base ones
%dataBlockName = %hTgt.getDataBlock().getName();
if (%dataBlockName $= "DeployedLTarget" && !isObject(%hTgt.lMain))
%canPerform = false;
if (%canPerform == true && (
%dataBlockName $= "StationInventory" ||
%dataBlockName $= "GeneratorLarge" ||
%dataBlockName $= "SolarPanel" ||
%dataBlockName $= "SensorMediumPulse" ||
%dataBlockName $= "SensorLargePulse"
))
if (%hTgt.deployed != true)
%canPerform = false;
if (%canPerform == true) {
// yes, it's usable
if (%hTgt != %obj.performing) { // its not what we were originally using
if (isObject(%obj.performing)) {
stopPerforming(%obj);
%obj.performing = %hTgt;
startPerforming(%obj);
}
}
else { // continue using
%obj.performTime = %obj.performTime - 120;
if (%obj.performTime < 0) { // we have a use!
if (%hTgt.team != %obj.team && !(%obj.client.isAdmin || %obj.client.isSuperAdmin)) {
messageClient(%obj.client, 'msgClient', '\c2Use failed! Wrong team!~wfx/powered/nexus_deny.wav');
stopPerforming(%obj);
return;
}
if (%obj.constructionToolMode2 == 0) {
if (%hTgt.getDataBlock().className !$= "Generator") {
messageClient(%obj.client, 'msgClient', '\c2Use failed! Not a generator!~wfx/powered/nexus_deny.wav');
stopPerforming(%obj);
return;
}
else {
%r = toggleGenerator(%hTgt);
%r1 = firstWord(%r);
%r2 = getTaggedString(getWord(%r,1));
%r3 = getWord(%r,2);
if (%r1 == -2)
messageClient(%obj.client, 'msgClient', '\c2Use failed! %1 is damaged!~wfx/powered/nexus_deny.wav',%r2);
else if (%r1 == -3)
messageClient(%obj.client, 'msgClient', '\c2Must wait %1 seconds before toggling power state.',mCeil(%r3/1000));
else if (%r1 == 1)
messageClient(%obj.client, 'msgClient', '\c2%1 switched off.',%r2);
else if (%r1 == 2)
messageClient(%obj.client, 'msgClient', '\c2%1 switched on.',%r2);
stopPerforming(%obj);
return;
}
}
if (%obj.constructionToolMode2 == 3) {
// if (%hTgt.powerFreq !$= "" || %hTgt.getDataBlock().needsPower) {
%numLines = 1;
if (%hTgt.powerFreq !$= "")
%msg = "Power frequency is " @ %hTgt.powerFreq @ ", power is " @ (%hTgt.isPowered() ? ((%hTgt.powerCount > 0) ? (%hTgt.powerCount) : "On") : "OFF");
else
%msg = "Item does not have power frequency set";
if (%hTgt.getOwner().nameBase !$= "") {
%numLines++;
%msg = %msg @ "\nThis belongs to " @ %hTgt.getOwner().nameBase;
}
if (%obj.client.isAdmin || %obj.client.isSuperAdmin) {
%numLines++;
%msg = %msg @ "\n [Owner Clientid]:" SPC %hTgt.getOwner() SPC "[Object id]:" SPC %htgt;
}
bottomPrint(%obj.client,%msg,2,%numLines);
stopPerforming(%obj);
// }
}
}
}
}
}
else
stopPerforming(%obj);
%obj.rotList = %list;
}