mirror of
https://github.com/mostlikely4r/construction-mod.git
synced 2026-01-19 19:24:44 +00:00
456 lines
12 KiB
C#
456 lines
12 KiB
C#
//--------------------------------------------------------------------------
|
|
// Datablocks
|
|
//--------------------------------------
|
|
|
|
datablock AudioProfile(MissileRackTurretFireSound) {
|
|
filename = "";
|
|
description = AudioDefault3d;
|
|
preload = true;
|
|
effect = MissileFireEffect;
|
|
};
|
|
|
|
datablock AudioProfile(MissileRackTurretFireSound2) {
|
|
filename = "fx/weapons/sniper_miss.wav";
|
|
description = AudioDefault3d;
|
|
preload = true;
|
|
};
|
|
|
|
datablock SensorData(MissileRackTurretSensor) {
|
|
detects = true;
|
|
detectsUsingLOS = true;
|
|
detectsPassiveJammed = false;
|
|
detectsActiveJammed = false;
|
|
detectsCloaked = false;
|
|
detectionPings = true;
|
|
detectRadius = 100;
|
|
};
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Explosions
|
|
//---------------------------------------------------------------------------
|
|
datablock ExplosionData(MissileRackMissileExplosion) {
|
|
explosionShape = "effect_plasma_explosion.dts";
|
|
playSpeed = 1.5;
|
|
soundProfile = GrenadeExplosionSound;
|
|
faceViewer = true;
|
|
|
|
sizes[0] = "0.5 0.5 0.5";
|
|
sizes[1] = "0.5 0.5 0.5";
|
|
sizes[2] = "0.5 0.5 0.5";
|
|
|
|
emitter[0] = MissileExplosionSmokeEmitter;
|
|
|
|
debris = MissileSpikeDebris;
|
|
debrisThetaMin = 10;
|
|
debrisThetaMax = 170;
|
|
debrisNum = 8;
|
|
debrisNumVariance = 6;
|
|
debrisVelocity = 15.0;
|
|
debrisVelocityVariance = 2.0;
|
|
|
|
shakeCamera = true;
|
|
camShakeFreq = "6.0 7.0 7.0";
|
|
camShakeAmp = "70.0 70.0 70.0";
|
|
camShakeDuration = 1.0;
|
|
camShakeRadius = 7.0;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Projectile
|
|
//--------------------------------------
|
|
datablock SeekerProjectileData(MissileRackMissile) {
|
|
casingShapeName = "weapon_missile_casement.dts";
|
|
projectileShapeName = "weapon_missile_projectile.dts";
|
|
hasDamageRadius = true;
|
|
indirectDamage = 0.2;
|
|
damageRadius = 4.0;
|
|
radiusDamageType = $DamageType::MissileTurret;
|
|
kickBackStrength = 1000;
|
|
|
|
explosion = "MissileRackMissileExplosion";
|
|
splash = MissileSplash;
|
|
velInheritFactor = 0.2; // to compensate for slow starting velocity, this value
|
|
// is cranked up to full so the missile doesn't start
|
|
// out behind the player when the player is moving
|
|
// very quickly - bramage
|
|
|
|
baseEmitter = MissileSmokeEmitter;
|
|
delayEmitter = MissileFireEmitter;
|
|
puffEmitter = MissilePuffEmitter;
|
|
bubbleEmitter = GrenadeBubbleEmitter;
|
|
bubbleEmitTime = 1.0;
|
|
|
|
exhaustEmitter = MissileLauncherExhaustEmitter;
|
|
exhaustTimeMs = 300;
|
|
exhaustNodeName = "muzzlePoint1";
|
|
|
|
lifetimeMS = 6000;
|
|
muzzleVelocity = 10.0;
|
|
maxVelocity = 80.0;
|
|
turningSpeed = 110.0;
|
|
acceleration = 200.0;
|
|
|
|
proximityRadius = 3;
|
|
|
|
terrainAvoidanceSpeed = 180;
|
|
terrainScanAhead = 25;
|
|
terrainHeightFail = 12;
|
|
terrainAvoidanceRadius = 100;
|
|
|
|
flareDistance = 200;
|
|
flareAngle = 30;
|
|
|
|
sound = MissileProjectileSound;
|
|
|
|
hasLight = true;
|
|
lightRadius = 5.0;
|
|
lightColor = "0.2 0.05 0";
|
|
|
|
useFlechette = true;
|
|
flechetteDelayMs = 550;
|
|
casingDeb = FlechetteDebris;
|
|
|
|
explodeOnWaterImpact = false;
|
|
};
|
|
|
|
datablock TurretData(MissileRackTurretDeployed) : TurretDamageProfile {
|
|
className = DeployedTurret;
|
|
shapeFile = "turret_outdoor_deploy.dts";
|
|
|
|
rechargeRate = 0.15;
|
|
|
|
mass = 1;
|
|
maxDamage = 0.80;
|
|
destroyedLevel = 0.80;
|
|
disabledLevel = 0.35;
|
|
|
|
explosion = HandGrenadeExplosion;
|
|
expDmgRadius = 5.0;
|
|
expDamage = 0.5;
|
|
expImpulse = 500.0;
|
|
|
|
repairRate = 0;
|
|
deployedObject = true;
|
|
|
|
thetaMin = 0;
|
|
thetaMax = 145;
|
|
thetaNull = 90;
|
|
primaryAxis = zaxis;
|
|
|
|
yawVariance = 30.0; // these will smooth out the elf tracking code.
|
|
pitchVariance = 30.0; // more or less just tolerances
|
|
|
|
isShielded = true;
|
|
energyPerDamagePoint = 110;
|
|
maxEnergy = 80;
|
|
renderWhenDestroyed = true;
|
|
barrel = DeployableMissileRackTurretBarrel;
|
|
heatSignature = 0.0;
|
|
|
|
canControl = true;
|
|
cmdCategory = "DTactical";
|
|
cmdIcon = CMDTurretIcon;
|
|
cmdMiniIconName = "commander/MiniIcons/com_turret_grey";
|
|
targetNameTag = 'Missile Rack';
|
|
targetTypeTag = 'Turret';
|
|
sensorData = MissileRackTurretSensor;
|
|
sensorRadius = MissileRackTurretSensor.detectRadius;
|
|
sensorColor = "191 0 226";
|
|
|
|
firstPersonOnly = true;
|
|
|
|
debrisShapeName = "debris_generic_small.dts";
|
|
debris = TurretDebrisSmall;
|
|
needsPower = true;
|
|
};
|
|
|
|
datablock TurretImageData(DeployableMissileRackTurretBarrel) {
|
|
shapeFile = "stackable1s.dts";
|
|
rotation = "-0.57735 0.57735 0.57735 120";
|
|
offset = "0 -0.3 0";
|
|
projectile = MissileRackMissile;
|
|
projectileType = SeekerProjectile;
|
|
|
|
usesEnergy = true;
|
|
fireEnergy = 7.0;
|
|
minEnergy = 7.0 * 2;
|
|
|
|
isSeeker = true;
|
|
seekRadius = 300;
|
|
maxSeekAngle = 30;
|
|
seekTime = 1.0;
|
|
minSeekHeat = 0.6;
|
|
emap = true;
|
|
minTargetingDistance = 15;
|
|
|
|
// Turret parameters
|
|
activationMS = 250;
|
|
deactivateDelayMS = 500;
|
|
thinkTimeMS = 200;
|
|
degPerSecTheta = 580;
|
|
degPerSecPhi = 1080;
|
|
attackRadius = 250;
|
|
|
|
// State transitions
|
|
stateName[0] = "Activate";
|
|
stateTransitionOnNotLoaded[0] = "Dead";
|
|
stateTransitionOnLoaded[0] = "ActivateReady";
|
|
|
|
stateName[1] = "ActivateReady";
|
|
stateSequence[1] = "Activate";
|
|
stateSound[1] = IBLSwitchSound;
|
|
|
|
stateTimeoutValue[1] = 1;
|
|
stateTransitionOnTimeout[1] = "Ready";
|
|
stateTransitionOnNotLoaded[1] = "Deactivate";
|
|
stateTransitionOnNoAmmo[1] = "NoAmmo";
|
|
|
|
stateName[2] = "Ready";
|
|
stateTransitionOnNotLoaded[2] = "Deactivate";
|
|
stateTransitionOnTriggerDown[2] = "Fire";
|
|
stateTransitionOnNoAmmo[2] = "NoAmmo";
|
|
|
|
stateName[3] = "Fire";
|
|
stateTransitionOnTimeout[3] = "Reload";
|
|
stateTimeoutValue[3] = 0.3;
|
|
stateFire[3] = true;
|
|
stateShockwave[3] = true;
|
|
stateRecoil[3] = LightRecoil;
|
|
stateAllowImageChange[3] = false;
|
|
stateSequence[3] = "Fire";
|
|
stateSound[3] = MissileRackTurretFireSound;
|
|
stateScript[3] = "onFire";
|
|
|
|
stateName[4] ="Reload";
|
|
stateTimeoutValue[4] = 0.5;
|
|
stateAllowImageChange[4] = false;
|
|
stateSequence[4] = "Reload";
|
|
stateTransitionOnTimeout[4] = "Ready";
|
|
stateTransitionOnNotLoaded[4] = "Deactivate";
|
|
stateTransitionOnNoAmmo[4] = "NoAmmo";
|
|
|
|
stateName[5] = "Deactivate";
|
|
stateSequence[5] = "Activate";
|
|
stateDirection[5] = false;
|
|
stateTimeoutValue[5] = 2;
|
|
stateTransitionOnLoaded[5] = "ActivateReady";
|
|
stateTransitionOnTimeout[5] = "Dead";
|
|
|
|
stateName[6] = "Dead";
|
|
stateTransitionOnLoaded[6] = "ActivateReady";
|
|
|
|
stateName[7] = "NoAmmo";
|
|
stateTransitionOnAmmo[7] = "Reload";
|
|
stateSequence[7] = "NoAmmo";
|
|
|
|
muzzleSlots = 12;
|
|
muzzleSlotOffset[0] = "0.65 0.5 0.4";
|
|
muzzleSlotOffset[1] = "0.35 0.5 0.4";
|
|
muzzleSlotOffset[2] = "0.15 0.5 0.4";
|
|
muzzleSlotOffset[3] = "-0.15 0.5 0.4";
|
|
muzzleSlotOffset[4] = "-0.35 0.5 0.4";
|
|
muzzleSlotOffset[5] = "-0.65 0.5 0.4";
|
|
muzzleSlotOffset[6] = "0.65 0.5 0.1";
|
|
muzzleSlotOffset[7] = "0.35 0.5 0.1";
|
|
muzzleSlotOffset[8] = "0.15 0.5 0.1";
|
|
muzzleSlotOffset[9] = "-0.15 0.5 0.1";
|
|
muzzleSlotOffset[10] = "-0.35 0.5 0.1";
|
|
muzzleSlotOffset[11] = "-0.65 0.5 0.1";
|
|
};
|
|
|
|
datablock TurretImageData(DeployableMissileRackTurretBarrelR) {
|
|
shapeFile = "stackable1s.dts";
|
|
rotation = "-0.57735 0.57735 0.57735 120";
|
|
offset = "0 -0.3 0.5";
|
|
|
|
};
|
|
|
|
datablock TurretImageData(DeployableMissileRackTurretBarrelL) {
|
|
shapeFile = "stackable1s.dts";
|
|
rotation = "-0.57735 0.57735 0.57735 120";
|
|
offset = "0 -0.3 -0.5";
|
|
};
|
|
|
|
function DeployableMissileRackTurretBarrel::onMount(%this,%obj,%slot) {
|
|
%obj.currentMuzzleSlot = 0;
|
|
%obj.schedule(1000,"mountImage",DeployableMissileRackTurretBarrelR,1,true);
|
|
%obj.schedule(1000,"mountImage",DeployableMissileRackTurretBarrelL,2,true);
|
|
}
|
|
|
|
// TODO - handle unmount
|
|
|
|
datablock ShapeBaseImageData(TurretMissileRackDeployableImage) {
|
|
mass = 1;
|
|
shapeFile = "pack_deploy_turreto.dts";
|
|
item = TurretMissileRackDeployable;
|
|
mountPoint = 1;
|
|
offset = "0 0 0";
|
|
deployed = MissileRackTurretDeployed;
|
|
stateName[0] = "Idle";
|
|
stateTransitionOnTriggerDown[0] = "Activate";
|
|
|
|
stateName[1] = "Activate";
|
|
stateScript[1] = "onActivate";
|
|
stateTransitionOnTriggerUp[1] = "Idle";
|
|
|
|
isLarge = true;
|
|
emap = true;
|
|
maxDepSlope = 360;
|
|
deploySound = TurretDeploySound;
|
|
minDeployDis = 0.5;
|
|
maxDeployDis = 5.0;
|
|
};
|
|
|
|
datablock ItemData(TurretMissileRackDeployable) {
|
|
className = Pack;
|
|
catagory = "Deployables";
|
|
shapeFile = "pack_deploy_turreti.dts";
|
|
mass = 1;
|
|
elasticity = 0.2;
|
|
friction = 0.6;
|
|
pickupRadius = 1;
|
|
rotate = false;
|
|
image = TurretMissileRackDeployableImage;
|
|
pickUpName = "a missile rack turret pack";
|
|
emap = true;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Functions
|
|
//--------------------------------------
|
|
|
|
function TurretMissileRackDeployableImage::TestNoTerrainFound(%item) {
|
|
// created to prevent console errors
|
|
}
|
|
|
|
function TurretMissileRackDeployableImage::TestNoInteriorFound(%item) {
|
|
// created to prevent console errors
|
|
}
|
|
|
|
function TurretMissileRackDeployable::onPickup(%this, %obj, %shape, %amount) {
|
|
//created to prevent console errors
|
|
}
|
|
|
|
function TurretMissileRackDeployableImage::onDeploy(%item, %plyr, %slot) {
|
|
%className = "Turret";
|
|
|
|
%playerVector = vectorNormalize(getWord(%plyr.getEyeVector(),1) SPC -1 * getWord(%plyr.getEyeVector(),0) SPC "0");
|
|
|
|
if (vAbs(floorVec(%item.surfaceNrm,100)) $= "0 0 1")
|
|
%item.surfaceNrm2 = %playerVector;
|
|
else
|
|
%item.surfaceNrm2 = vectorNormalize(vectorCross(%item.surfaceNrm,"0 0 1"));
|
|
|
|
%rot = fullRot(%item.surfaceNrm,%item.surfaceNrm2);
|
|
|
|
%deplObj = new (%className)() {
|
|
dataBlock = %item.deployed;
|
|
};
|
|
|
|
if (%plyr.packSet == 1)
|
|
%deplObj.isSeeker = true;
|
|
|
|
// set orientation
|
|
%deplObj.setTransform(%item.surfacePt SPC %rot);
|
|
|
|
// set team, owner, and handle
|
|
%deplObj.team = %plyr.client.Team;
|
|
%deplObj.setOwner(%plyr);
|
|
|
|
// set power frequency
|
|
%deplObj.powerFreq = %plyr.powerFreq;
|
|
|
|
// set the sensor group if it needs one
|
|
if (%deplObj.getTarget() != -1)
|
|
setTargetSensorGroup(%deplObj.getTarget(), %plyr.client.team);
|
|
|
|
// place the deployable in the MissionCleanup/Deployables group (AI reasons)
|
|
addToDeployGroup(%deplObj);
|
|
|
|
//let the AI know as well...
|
|
AIDeployObject(%plyr.client, %deplObj);
|
|
|
|
// play the deploy sound
|
|
serverPlay3D(%item.deploySound, %deplObj.getTransform());
|
|
|
|
// increment the team count for this deployed object
|
|
$TeamDeployedCount[%plyr.team, %item.item]++;
|
|
|
|
%deplObj.deploy();
|
|
|
|
// Power object
|
|
checkPowerObject(%deplObj);
|
|
|
|
addDSurface(%item.surface,%deplObj);
|
|
|
|
// take the deployable off the player's back and out of inventory
|
|
%plyr.unmountImage(%slot);
|
|
%plyr.decInventory(%item.item, 1);
|
|
|
|
return %deplObj;
|
|
}
|
|
|
|
function MissileRackTurretDeployed::onDestroyed(%this, %obj, %prevState) {
|
|
if (%obj.isRemoved)
|
|
return;
|
|
if ($Host::InvincibleDeployables != 1 || %obj.damageFailedDecon) {
|
|
%obj.isRemoved = true;
|
|
$TeamDeployedCount[%obj.team, TurretMissileRackDeployable]--;
|
|
remDSurface(%obj);
|
|
%obj.schedule(500, delete);
|
|
}
|
|
Parent::onDestroyed(%this, %obj, %prevState);
|
|
}
|
|
|
|
function DeployableMissileRackTurretBarrel::onFire(%data,%obj,%slot) {
|
|
%targetObj = %obj.getTargetObject();
|
|
if (%targetObj) {
|
|
if (!%obj.getDataBlock().hasLOS(%obj,%slot,%targetObj) && %obj.aquireTime + 2000 < getSimTime()) {
|
|
%obj.clearTarget();
|
|
return;
|
|
}
|
|
if (%obj.aquireTime + 10000 + getRandom(0,1000) < getSimTime()) {
|
|
%obj.clearTarget();
|
|
return;
|
|
}
|
|
}
|
|
|
|
%p = Parent::onFire(%data,%obj,%slot);
|
|
serverPlay3D(MissileRackTurretFireSound2,%obj.getTransform());
|
|
|
|
if (%obj.isSeeker) {
|
|
if (%obj.getControllingClient())
|
|
// a player is controlling the turret
|
|
%target = %obj.getLockedTarget();
|
|
else
|
|
// The ai is controlling the turret
|
|
%target = %obj.getTargetObject();
|
|
|
|
if(%target)
|
|
%p.setObjectTarget(%target);
|
|
else if(%obj.isLocked())
|
|
%p.setPositionTarget(%obj.getLockedPosition());
|
|
else
|
|
%p.setNoTarget(); // set as unguided. Only happens when itchy trigger can't wait for lock tone.
|
|
%obj.setEnergyLevel(%obj.getEnergyLevel() - (%data.fireEnergy));
|
|
}
|
|
}
|
|
|
|
function MissileRackTurretDeployed::hasLOS(%data,%obj,%slot,%targetObj) {
|
|
%start = %obj.getMuzzlePoint(%slot);
|
|
%end = %targetObj.getWorldBoxCenter();
|
|
%res = containerRayCast(%start,%end,-1,%obj);
|
|
return firstWord(%res) == %targetObj;
|
|
}
|
|
|
|
function TurretMissileRackDeployableImage::onMount(%data, %obj, %node) {
|
|
%obj.hasMissileRack = true; // set for missilerackcheck
|
|
%obj.packSet = 0;
|
|
displayPowerFreq(%obj);
|
|
}
|
|
|
|
function TurretMissileRackDeployableImage::onUnmount(%data, %obj, %node) {
|
|
%obj.hasMissileRack = "";
|
|
%obj.packSet = 0;
|
|
}
|