mirror of
https://github.com/Ragora/T2-ACCM.git
synced 2026-01-20 03:14:44 +00:00
722 lines
24 KiB
C#
722 lines
24 KiB
C#
//------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------
|
|
// Drone AI by Dondelium_X
|
|
// CCM v3.4
|
|
//------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------
|
|
|
|
$Drone::DetectDist = 500;
|
|
$Drone::TurnImpulse = 123;
|
|
$Drone::FrdImpulse = 525;
|
|
//$Drone::TurnImpulse = 675 / 3;
|
|
//$Drone::FrdImpulse = 525 * 3;
|
|
$Drone::newTargetChance = "1 100";
|
|
|
|
$Drone::paths = 4;
|
|
$Drone::path[1,1] = "0 1500 1000";
|
|
$Drone::path[1,2] = "1500 0 1000";
|
|
$Drone::path[1,3] = "0 -1500 1000";
|
|
$Drone::path[1,4] = "-1500 0 1000";
|
|
|
|
$Drone::path[2,1] = "0 -1500 1000";
|
|
$Drone::path[2,2] = "-1500 0 1000";
|
|
$Drone::path[2,3] = "0 1500 1000";
|
|
$Drone::path[2,4] = "1500 0 1000";
|
|
|
|
$Drone::path[3,1] = "0 2500 750";
|
|
$Drone::path[3,2] = "0 2500 1250";
|
|
$Drone::path[3,3] = "0 -2500 1250";
|
|
$Drone::path[3,4] = "0 -2500 750";
|
|
|
|
$Drone::path[4,1] = "2500 0 750";
|
|
$Drone::path[4,2] = "2500 0 1250";
|
|
$Drone::path[4,3] = "-2500 0 1250";
|
|
$Drone::path[4,4] = "-2500 0 750";
|
|
|
|
//-----Manuver Index-----
|
|
|
|
$flightManuvers::Behind[0] = Immelman;
|
|
$flightManuvers::Behind[1] = HalfFlip;
|
|
$flightManuvers::Behind[2] = BreakRight;
|
|
$flightManuvers::Behind[3] = BreakLeft;
|
|
$flightManuvers::Behind[4] = BarrelRoll;
|
|
$flightManuvers::Behind[5] = WingWaggle;
|
|
$flightManuvers::Behind[6] = Reversal;
|
|
|
|
|
|
//-----Manuvers-----
|
|
|
|
//Immelman
|
|
$flightManuver::Points[Immelman] = 5; //This signifies how many points are in the manuver
|
|
$flightManuver::Point[Immelman,0] = "0 1 0 0 0 1"; //each point represents the 3 numbers of the vector of the desired forward vector,
|
|
$flightManuver::Point[Immelman,1] = "0 0 1 0 -1 0"; //and then the 3 numbers of the vector for the desired Up vector
|
|
$flightManuver::Point[Immelman,2] = "0 -1 0 0 0 -1";
|
|
$flightManuver::Point[Immelman,3] = "0 -1 0 1 0 0";
|
|
$flightManuver::Point[Immelman,4] = "0 -1 0 0 0 1";
|
|
|
|
//halfFlip
|
|
$flightManuver::Points[HalfFlip] = 3;
|
|
$flightManuver::Point[HalfFlip,0] = "0 1 0 0 0 1";
|
|
$flightManuver::Point[HalfFlip,1] = "0 0 1 0 -1 0";
|
|
$flightManuver::Point[HalfFlip,2] = "0 -1 0 0 0 -1";
|
|
|
|
//breakRight
|
|
$flightManuver::Points[BreakRight] = 3;
|
|
$flightManuver::Point[BreakRight,0] = "0 1 0 0 0 1";
|
|
$flightManuver::Point[BreakRight,1] = "0 1 0 1 0 0";
|
|
$flightManuver::Point[BreakRight,2] = "1 0 0 0 -1 0";
|
|
|
|
//BreakLeft
|
|
$flightManuver::Points[BreakLeft] = 3;
|
|
$flightManuver::Point[BreakLeft,0] = "0 1 0 0 0 1";
|
|
$flightManuver::Point[BreakLeft,1] = "0 1 0 -1 0 0";
|
|
$flightManuver::Point[BreakLeft,2] = "-1 0 0 0 -1 0";
|
|
|
|
//BarrelRoll
|
|
$flightManuver::Points[BarrelRoll] = 5;
|
|
$flightManuver::Point[BarrelRoll,0] = "0 1 0 0 0 1";
|
|
$flightManuver::Point[BarrelRoll,1] = "0 1 0 1 0 0";
|
|
$flightManuver::Point[BarrelRoll,2] = "0 1 0 0 0 -1";
|
|
$flightManuver::Point[BarrelRoll,3] = "0 1 0 -1 0 0";
|
|
$flightManuver::Point[BarrelRoll,4] = "0 1 0 0 0 1";
|
|
|
|
//WingWaggle
|
|
$flightManuver::Points[WingWaggle] = 4;
|
|
$flightManuver::Point[WingWaggle,0] = "0 1 0 0 0 1";
|
|
$flightManuver::Point[WingWaggle,1] = "-1 1 0 0 0 1";
|
|
$flightManuver::Point[WingWaggle,2] = "1 1 0 0 0 1";
|
|
$flightManuver::Point[WingWaggle,3] = "0 1 0 0 0 1";
|
|
|
|
//Reversal
|
|
$flightManuver::Points[Reversal] = 7;
|
|
$flightManuver::Point[Reversal,0] = "0 1 0 0 0 1";
|
|
$flightManuver::Point[Reversal,1] = "0 0 1 0 -1 0";
|
|
$flightManuver::Point[Reversal,2] = "0 0 1 1 0 0";
|
|
$flightManuver::Point[Reversal,3] = "1 0 0 0 0 -1";
|
|
$flightManuver::Point[Reversal,4] = "0 0 -1 -1 0 0";
|
|
$flightManuver::Point[Reversal,5] = "0 0 -1 0 1 0";
|
|
$flightManuver::Point[Reversal,6] = "0 1 0 0 0 1";
|
|
|
|
//This is a function for mass spawning
|
|
function DroneBattle(%pos, %radius, %number, %teamlow, %teamhigh, %maxskill){
|
|
for(%i = 0; %i < %number; %i++){
|
|
%startpos = vectorAdd(%pos,(getRandom(0, %radius) - (%radius / 2))@" "@(getRandom(0, %radius) - (%radius / 2))@" 0");
|
|
%rotation = "0 0 1 "@getRandom(1,360);
|
|
if(%teamlow != %teamhigh)
|
|
%team = getRandom(%teamlow,%teamhigh);
|
|
else
|
|
%team = %teamlow;
|
|
StartDrone(%startpos,%rotation,%team,getRandom(1,%maxskill));
|
|
}
|
|
}
|
|
|
|
//This sets up the drone and the functions needed to start the drone.
|
|
function StartDrone(%pos, %rotation, %team, %skill){
|
|
if(%team $= "")
|
|
%team = 0;
|
|
if(%pos $= "")
|
|
%pos = "0 0 300";
|
|
if(%rotation $= "")
|
|
%rotation = "1 0 0 0";
|
|
if(%skill !$= "ace"){
|
|
if(%skill $= "" || %skill < 1)
|
|
%skill = 1;
|
|
else if(%skill > 10)
|
|
%skill = 10;
|
|
}
|
|
%Drone = new FlyingVehicle()
|
|
{
|
|
dataBlock = ScoutFlyer;
|
|
position = %pos;
|
|
rotation = %rotation;
|
|
team = %team;
|
|
};
|
|
MissionCleanUp.add(%Drone);
|
|
|
|
setTargetSensorGroup(%Drone.getTarget(), %team);
|
|
|
|
%drone.isdrone = 1;
|
|
%drone.dodgeGround = 0;
|
|
|
|
if(%skill $= "ace"){
|
|
%skill = 10;
|
|
%drone.isace = 1;
|
|
}
|
|
|
|
%drone.skill = 0.2 + (%skill / 12.5);
|
|
|
|
schedule(100, 0, "DroneForwardImpulse", %drone);
|
|
schedule(101, 0, "DronefindTarget", %drone);
|
|
schedule(102, 0, "DroneScanGround", %drone);
|
|
|
|
return %drone;
|
|
}
|
|
|
|
//This makes the drone move forward until it dies
|
|
function DroneForwardImpulse(%obj){
|
|
if(!isObject(%obj))
|
|
return;
|
|
if(!%obj.isace){
|
|
if(vectorLen(%obj.getVelocity()) < 165)
|
|
%obj.applyImpulse(%obj.getPosition(),vectorScale(%obj.getForwardVector(),$Drone::FrdImpulse));
|
|
}
|
|
else{
|
|
if(vectorLen(%obj.getVelocity()) < 225)
|
|
%obj.applyImpulse(%obj.getPosition(),vectorScale(%obj.getForwardVector(),$Drone::FrdImpulse * 3));
|
|
}
|
|
schedule(100, 0, "DroneForwardImpulse", %obj);
|
|
}
|
|
|
|
function DroneScanGround(%obj){
|
|
if(!isObject(%obj))
|
|
return;
|
|
%vec = %obj.getForwardVector();
|
|
%vector = vectorAdd(%obj.getPosition(),"0 0 -500");
|
|
%searchResult = containerRayCast(%obj.getWorldBoxCenter(), %vector, $TypeMasks::TerrainObjectType, %obj);
|
|
if(%searchResult){
|
|
%z = getWord(%vec,2);
|
|
%height = vectorDist(%obj.getPosition(),posFromRaycast(%searchresult));
|
|
if(%z < 0){
|
|
if(%height <= (200 + ((%z * -1) * 300))){
|
|
%obj.dodgeground = 1;
|
|
schedule(100, 0, "DroneDodgeGround", %obj);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
schedule(100, 0, "DroneScanGround", %obj);
|
|
}
|
|
|
|
function DroneDodgeGround(%obj){
|
|
if(!isObject(%obj))
|
|
return;
|
|
%vec = %obj.getForwardVector();
|
|
%z = getWord(%vec,2);
|
|
if(%z > 0){
|
|
%obj.dodgeground = 0;
|
|
schedule(100, 0, "DronefindTarget", %obj);
|
|
schedule(101, 0, "DroneScanGround", %obj);
|
|
return;
|
|
}
|
|
%pos = vectorAdd(%obj.getPosition(),%vec);
|
|
%obj.applyImpulse(%pos,vectorScale("0 0 1",$Drone::TurnImpulse * %obj.skill));
|
|
schedule(100, 0, "DroneDodgeGround", %obj);
|
|
}
|
|
|
|
//This function checks the area around it for any targets.
|
|
function DronefindTarget(%obj){
|
|
if(!isObject(%obj))
|
|
return;
|
|
%pos = %obj.getposition();
|
|
InitContainerRadiusSearch(%pos, $drone::detectdist + (800 + (600 * %obj.skill)), $TypeMasks::VehicleObjectType);
|
|
while ((%searchResult = containerSearchNext()) != 0){
|
|
%objtarget = firstWord(%searchResult);
|
|
if(isObject(%objtarget) && %objTarget !$= %obj){
|
|
%trgtype = %objtarget.getClassName();
|
|
if(%trgtype $= "FlyingVehicle" && %objtarget.team != %obj.team){
|
|
%testPos = %objtarget.getWorldBoxCenter();
|
|
%distance = vectorDist(%objtarget.getPosition(),%pos);
|
|
if (%distance > 0){
|
|
%target = %objtarget;
|
|
DroneDetermineManuver(%obj, %target);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
schedule(100, 0, "DronePatrol", %obj);
|
|
}
|
|
|
|
function DronePatrol(%obj){
|
|
if(!isObject(%obj))
|
|
return;
|
|
if($Drone::paths > 0){
|
|
if(%obj.path $= ""){
|
|
%obj.path = getRandom(1,$Drone::paths);
|
|
%obj.point = 0;
|
|
}
|
|
%obj.point++;
|
|
if($Drone::path[%obj.path,%obj.point] $= ""){
|
|
schedule(100, 0, "DronefindTarget", %obj);
|
|
%obj.path = "";
|
|
%obj.point = "";
|
|
}
|
|
else
|
|
schedule(100,0,"dronemovetopoint",%obj,$Drone::path[%obj.path,%obj.point]);
|
|
}
|
|
else
|
|
schedule(500, 0, "DronefindTarget", %obj);
|
|
}
|
|
|
|
function DroneMoveToPoint(%obj,%Tpos){
|
|
if(!isObject(%obj))
|
|
return;
|
|
if(%obj.dodgeground == 1)
|
|
return;
|
|
%pos = %obj.getPosition();
|
|
%objfrd = %obj.getForwardVector();
|
|
%objup = %obj.getUpVector();
|
|
|
|
%dist = vectorDist(%pos,%Tpos);
|
|
%aimvec = vectorNormalize(vectorSub(%Tpos,%pos));
|
|
|
|
%vec = vectorSub(%aimvec , %objfrd);
|
|
%vec = vectorCross(%vec, %objfrd);
|
|
%vec = vectorNormalize(vectorCross(%objfrd, %vec));
|
|
if(vectorDist(%objfrd,vectorNormalize(%aimvec)) < 0.1)
|
|
%obj.applyImpulse(vectorAdd(%obj.getPosition(),vectorScale(%objfrd,($Drone::TurnImpulse / 2))),%vec);
|
|
else if(vectorDist(%objup, %vec) > 0.1){
|
|
%vec = vectorSub(%vec, %objup);
|
|
%vec = vectorCross(%vec, %objup);
|
|
%vec = vectorNormalize(vectorCross(%objup, %vec));
|
|
%pos = vectorAdd(%obj.getPosition(),vectorScale(%objup,$Drone::TurnImpulse * 3 * %obj.skill));
|
|
%obj.applyImpulse(%pos,%vec);
|
|
}
|
|
else
|
|
%obj.applyImpulse(vectorAdd(%obj.getPosition(),%objfrd),vectorScale(%vec,$Drone::TurnImpulse * %obj.skill));
|
|
if(getRandom(0,getWord($Drone::newTargetChance,1)) <= (getWord($Drone::newTargetChance,0) * 10))
|
|
schedule(100, 0, "DronefindTarget", %obj, %target);
|
|
else if(%dist < 25)
|
|
schedule(100, 0, "DronePatrol", %obj);
|
|
else
|
|
schedule(100, 0, "DroneMoveToPoint", %obj, %tpos);
|
|
}
|
|
|
|
//This function figures out what the drone should do from where the target is.
|
|
function DroneDetermineManuver(%obj, %target){
|
|
if(!isObject(%obj))
|
|
return;
|
|
if(!isObject(%target)){
|
|
DronefindTarget(%obj);
|
|
return;
|
|
}
|
|
%pos = %obj.getPosition();
|
|
%Tpos = %Target.getPosition();
|
|
%objfrd = %obj.getForwardVector();
|
|
%trgfrd = %target.getForwardVector();
|
|
%vec = vectorSub(%Tpos,%pos);
|
|
%dirdist = vectorDist(%objfrd,vectorNormalize(%vec));
|
|
%vecdist = vectorDist(%objfrd,%trgfrd);
|
|
if(%dirdist > 1.41){
|
|
if(%vecdist < 1.41 && vectorDist(%pos,%Tpos) < 2000){
|
|
UnderFireManuver(%obj, $flightManuvers::Behind[getRandom(0,6)], "");
|
|
}
|
|
else
|
|
TurnToFire(%obj, %target);
|
|
}
|
|
else
|
|
TurnToFire(%obj, %target);
|
|
%obj.target = %target;
|
|
}
|
|
|
|
function TurnToFire(%obj, %target){
|
|
if(!isObject(%obj))
|
|
return;
|
|
if(!isObject(%target)){
|
|
DronefindTarget(%obj);
|
|
return;
|
|
}
|
|
if(%obj.dodgeground == 1)
|
|
return;
|
|
|
|
%pos = %obj.getPosition();
|
|
%Tpos = %target.getPosition();
|
|
%objfrd = %obj.getForwardVector();
|
|
%trgfrd = %target.getForwardVector();
|
|
%objup = %obj.getUpVector();
|
|
%Tvel = %target.getVelocity();
|
|
|
|
%dist = vectorDist(%pos,%Tpos);
|
|
%aimPos = vectorAdd(%Tpos, vectorScale(%Tvel,(%dist / 1750)));
|
|
%aimvec = vectorNormalize(vectorSub(%aimPos,%pos));
|
|
|
|
if(vectorDist(%objfrd,%aimvec) < 0.1 && %dist <= 1000){
|
|
if((vectorDist(%objfrd,%trgfrd) < 0.2 || vectorDist(%objfrd,%trgfrd) > 1.8) && %obj.missiling != 1){
|
|
%obj.setImageTrigger(4, true);
|
|
%obj.missiling = 1;
|
|
}
|
|
else if(%obj.missiling == 1){
|
|
%obj.setImageTrigger(4, false);
|
|
%obj.missiling = 0;
|
|
}
|
|
// if (%obj.firing != 1){
|
|
%obj.setImageTrigger(2, true);
|
|
%obj.setImageTrigger(3, true);
|
|
%obj.firing = 1;
|
|
// }
|
|
}
|
|
else{
|
|
if(%obj.firing == 1){
|
|
%obj.setImageTrigger(2, false);
|
|
%obj.setImageTrigger(3, false);
|
|
%obj.firing = 0;
|
|
}
|
|
if(%obj.missiling == 1){
|
|
%obj.setImageTrigger(4, false);
|
|
%obj.missiling = 0;
|
|
}
|
|
}
|
|
%vec = vectorSub(%aimvec , %objfrd);
|
|
%vec = vectorCross(%vec, %objfrd);
|
|
%vec = vectorNormalize(vectorCross(%objfrd, %vec));
|
|
if(vectorDist(%objfrd,%trgfrd) > 1.8 && %dist <= 120){
|
|
%vec = vectorScale(%vec, -1);
|
|
if(vectorDist(%objfrd,vectorNormalize(%aimvec)) > 1.8)
|
|
%obj.applyImpulse(vectorAdd(%obj.getPosition(),vectorScale(%objfrd,($Drone::TurnImpulse / 2))),%vec);
|
|
else if(vectorDist(%objup, %vec) > 0.1){
|
|
%vec = vectorSub(%vec, %objup);
|
|
%vec = vectorCross(%vec, %objup);
|
|
%vec = vectorNormalize(vectorCross(%objup, %vec));
|
|
%pos = vectorAdd(%obj.getPosition(),vectorScale(%objup,$Drone::TurnImpulse * 3 * %obj.skill));
|
|
%obj.applyImpulse(%pos,%vec);
|
|
}
|
|
else
|
|
%obj.applyImpulse(vectorAdd(%obj.getPosition(),%objfrd),vectorScale(%vec,$Drone::TurnImpulse * %obj.skill));
|
|
}
|
|
else if(vectorDist(%objfrd,vectorNormalize(%aimvec)) < 0.1)
|
|
%obj.applyImpulse(vectorAdd(%obj.getPosition(),vectorScale(%objfrd,($Drone::TurnImpulse / 2))),%vec);
|
|
else if(vectorDist(%objup, %vec) > 0.1){
|
|
%vec = vectorSub(%vec, %objup);
|
|
%vec = vectorCross(%vec, %objup);
|
|
%vec = vectorNormalize(vectorCross(%objup, %vec));
|
|
%pos = vectorAdd(%obj.getPosition(),vectorScale(%objup,$Drone::TurnImpulse * 3 * %obj.skill));
|
|
%obj.applyImpulse(%pos,%vec);
|
|
}
|
|
else
|
|
%obj.applyImpulse(vectorAdd(%obj.getPosition(),%objfrd),vectorScale(%vec,$Drone::TurnImpulse * %obj.skill));
|
|
if(getRandom(0,getWord($Drone::newTargetChance,1)) <= getWord($Drone::newTargetChance,0))
|
|
schedule(100, 0, "DronefindTarget", %obj, %target);
|
|
else
|
|
schedule(100, 0, "TurnToFire", %obj, %target);
|
|
}
|
|
|
|
//This function preforms the manuver choosen in Determine Maunver function.
|
|
function UnderFireManuver(%obj, %manuver, %point, %count){
|
|
if(!isObject(%obj))
|
|
return;
|
|
if(%obj.dodgeground == 1)
|
|
return;
|
|
if(%count $= "")
|
|
%count = 0;
|
|
if(%point $= ""){
|
|
%point = 0;
|
|
SetPointVectors(%obj, %manuver);
|
|
}
|
|
if(%count >= 30){
|
|
schedule(100, 0, "DroneDetermineManuver", %obj, %obj.target);
|
|
return;
|
|
}
|
|
%frdvec = %obj.getForwardVector();
|
|
%upvec = %obj.getUpVector();
|
|
if(vectorDist(%frdvec, %obj.pointvecfront[%point]) < 0.15 && vectorDist(%upvec, %obj.pointvectop[%point]) < 0.15){
|
|
%point++;
|
|
if(%point < $flightManuver::Points[%manuver])
|
|
schedule(100, 0, "UnderFireManuver", %obj, %manuver, %point, 0);
|
|
else
|
|
schedule(100, 0, "DroneDetermineManuver", %obj, %obj.target);
|
|
return;
|
|
}
|
|
if(vectorDist(%frdvec, %obj.pointvecfront[%point]) > 0.1){
|
|
%vec = vectorSub(%obj.pointvecfront[%point], %frdvec);
|
|
%vec = vectorCross(%vec, %frdvec);
|
|
%vec = vectorCross(%frdvec, %vec);
|
|
%obj.applyImpulse(vectorAdd(%obj.getPosition(),vectorScale(%frdvec,$Drone::TurnImpulse * %obj.skill)),%vec);
|
|
}
|
|
if(vectorDist(%upvec, %obj.pointvectop[%point]) > 0.1){
|
|
%vec = vectorSub(%obj.pointvectop[%point], %upvec);
|
|
%vec = vectorCross(%vec, %upvec);
|
|
%vec = vectorCross(%upvec, %vec);
|
|
%pos = vectorAdd(%obj.getPosition(),vectorScale(%upvec,$Drone::TurnImpulse * 3 * %obj.skill));
|
|
%obj.applyImpulse(%pos,%vec);
|
|
}
|
|
%count++;
|
|
schedule(100, 0, "UnderFireManuver", %obj, %manuver, %point, %count);
|
|
}
|
|
|
|
//This function finds what vectors each point in the manuver is compaired to the drone.
|
|
function SetPointVectors(%obj, %manuver){
|
|
%up = %obj.getUpVector();
|
|
%forward = %obj.getForwardVector();
|
|
%right = vectorNormalize(vectorSub(%obj.getEdge("1 0 0"),%obj.getEdge("-1 0 0")));
|
|
for(%i = 0; %i < $flightManuver::Points[%manuver]; %i++){
|
|
%pointdir = $flightManuver::Point[%manuver, %i];
|
|
%topvec = "0 0 0";
|
|
%frontvec = "0 0 0";
|
|
if(getWord(%pointdir, 0) > 0)
|
|
%frontvec = vectorAdd(%frontvec, %right);
|
|
else if(getWord(%pointdir, 0) < 0)
|
|
%frontvec = vectorAdd(%frontvec, vectorScale(%right, -1));
|
|
if(getWord(%pointdir, 1) > 0)
|
|
%frontvec = vectorAdd(%frontvec, %forward);
|
|
else if(getWord(%pointdir, 1) < 0)
|
|
%frontvec = vectorAdd(%frontvec, vectorScale(%forward, -1));
|
|
if(getWord(%pointdir, 2) > 0)
|
|
%frontvec = vectorAdd(%frontvec, %up);
|
|
else if(getWord(%pointdir, 2) < 0)
|
|
%frontvec = vectorAdd(%frontvec, vectorScale(%up, -1));
|
|
|
|
if(getWord(%pointdir, 3) > 0)
|
|
%topvec = vectorAdd(%topvec, %right);
|
|
else if(getWord(%pointdir, 3) < 0)
|
|
%topvec = vectorAdd(%topvec, vectorScale(%right, -1));
|
|
if(getWord(%pointdir, 4) > 0)
|
|
%topvec = vectorAdd(%topvec, %forward);
|
|
else if(getWord(%pointdir, 4) < 0)
|
|
%topvec = vectorAdd(%topvec, vectorScale(%forward, -1));
|
|
if(getWord(%pointdir, 5) > 0)
|
|
%topvec = vectorAdd(%topvec, %up);
|
|
else if(getWord(%pointdir, 5) < 0)
|
|
%topvec = vectorAdd(%topvec, vectorScale(%up, -1));
|
|
|
|
%obj.pointvecfront[%i] = vectorNormalize(%frontvec);
|
|
%obj.pointvectop[%i] = vectorNormalize(%topvec);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------
|
|
// Tank AI by Dondelium_X
|
|
// CCM v3.4
|
|
//------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------
|
|
$DTank::ForwardForce = 7000;
|
|
$DTank::BackForce = 3000;
|
|
$DTank::TurnForce = 2500;
|
|
|
|
function StartDTank(%pos,%team,%skill){
|
|
if(%team $= "")
|
|
%team = 0;
|
|
if(%pos $= "")
|
|
%pos = "0 0 300";
|
|
if(%skill $= "" || %skill < 1)
|
|
%skill = 1;
|
|
else if(%skill > 10)
|
|
%skill = 10;
|
|
|
|
%Drone = new HoverVehicle()
|
|
{
|
|
dataBlock = HeavyTank;
|
|
position = %pos;
|
|
rotation = "0 0 1 0";
|
|
team = %team;
|
|
};
|
|
MissionCleanUp.add(%Drone);
|
|
|
|
setTargetSensorGroup(%Drone.getTarget(), %team);
|
|
|
|
%drone.skill = 0.6 + (%skill / 25);
|
|
|
|
schedule(100, 0, "DTankScanTargets",%drone);
|
|
}
|
|
|
|
function DTankScanTargets(%obj){
|
|
if(!isObject(%obj))
|
|
return;
|
|
%pos = %obj.getposition();
|
|
%closestClient = -1;
|
|
%closestDistance = 32767;
|
|
%scandist = 2000 * %obj.skill;
|
|
%airtrgs = "";
|
|
%groundtrgs = "";
|
|
%inftrgs = "";
|
|
InitContainerRadiusSearch(%pos, %scanDist, $TypeMasks::VehicleObjectType | $TypeMasks::PlayerObjectType);
|
|
while ((%searchResult = containerSearchNext()) != 0){
|
|
%objtarget = firstWord(%searchResult);
|
|
if(isObject(%objtarget) && %objTarget !$= %obj && %objtarget.team != %obj.team){
|
|
%trgtype = %objtarget.getClassName();
|
|
if(%trgtype $= "FlyingVehicle")
|
|
%airtrgs = %airtrgs SPC %objtarget;
|
|
else if(%trgtype $= "HoverVehicle")
|
|
%groundtrgs = %groundtrgs SPC %objtarget;
|
|
else if(%trgtype $= "Player")
|
|
%inftrgs = %inftrgs SPC %objtarget;
|
|
}
|
|
}
|
|
if(%groundtrgs){
|
|
%target = firstWord(%groundtrgs);
|
|
%groundtrgs = getWords(%groundtrgs,1,4);
|
|
DTankGroundCombat(%obj, %target,%groundtrgs);
|
|
}
|
|
else if(%inftrgs){
|
|
%target = firstWord(%inftrgs);
|
|
%inftrgs = getWords(%inftrgs,1,4);
|
|
DTankInfCombat(%obj, %target,%inftrgs);
|
|
}
|
|
else if(%airtrgs){
|
|
%target = firstWord(%airtrgs);
|
|
%airtrgs = getWords(%airtrgs,1,4);
|
|
DTankAACombat(%obj, %target,%airtrgs);
|
|
}
|
|
else{
|
|
schedule(3000, 0, "DTankScanTargets", %obj);
|
|
}
|
|
}
|
|
|
|
function DTankGroundCombat(%obj, %target, %Trglist){
|
|
if(!isObject(%obj))
|
|
return;
|
|
if(!isObject(%target)){
|
|
%obj.turretobject.setImageTrigger(4,false);
|
|
%obj.firing = "";
|
|
if(%TrgList){
|
|
%target = firstWord(%Trglist);
|
|
%trglist = getWords(%trglist,1,4);
|
|
}
|
|
else{
|
|
DTankScanTargets(%obj);
|
|
return;
|
|
}
|
|
}
|
|
%pos = %obj.getPosition();
|
|
%tpos = %target.getPosition();
|
|
%frdvec = vectorNormalize(getWords(%obj.getForwardVector(),0,1) SPC "0");
|
|
%chkvec = vectorSub(%tpos,%pos);
|
|
%chkvec = vectorNormalize(getWords(%chkvec,0,1) SPC "0");
|
|
%turnvec = vectorsub(%chkvec,%frdvec);
|
|
%vecdif = vectorlen(%turnvec);
|
|
if(vectorDist(%pos,%tpos) > 2000){
|
|
if(%obj.firing){
|
|
%obj.firing = "";
|
|
%obj.turret.setImageTrigger(4,false);
|
|
}
|
|
%target = "";
|
|
}
|
|
else if(vectorDist(%pos,%tpos) > 500){
|
|
if(%vecdif >= "0.1"){
|
|
%vec = vectorCross(%turnvec, %frdvec);
|
|
%vec = vectorNormalize(vectorCross(%obj.getForwardVector(), %vec));
|
|
%Imppos = vectorAdd(%pos,%obj.getForwardVector());
|
|
%obj.applyImpulse(%Imppos,vectorScale(%vec,$DTank::TurnForce * %obj.skill));
|
|
}
|
|
}
|
|
else{
|
|
if(!%obj.firing){
|
|
%obj.firing = 1;
|
|
%obj.turretobject.firetype = 3;
|
|
%obj.turretobject.setTargetObject(%Target);
|
|
%obj.turretobject.aquireTime = getSimTime();
|
|
%obj.turretobject.setImageTrigger(4,true);
|
|
}
|
|
if(%vecdif < "1.2" || %vecdif >= "1.6"){
|
|
%Tvec1 = vectorNormalize(vectorcross(%chkvec,"0 0 1"));
|
|
%Tvec2 = vectorScale(%Tvec1,-1);
|
|
if(vectordist(%frdvec,%Tvec1) < vectorDist(%frdvec,%Tvec2))
|
|
%tovec = vectorSub(%Tvec1,%frdvec);
|
|
else
|
|
%tovec = vectorSub(%Tvec2,%frdvec);
|
|
%vec = vectorCross(%Tvec2, %frdvec);
|
|
%vec = vectorNormalize(vectorCross(%obj.getForwardVector(), %vec));
|
|
%Imppos = vectorAdd(%pos,%obj.getForwardVector());
|
|
%obj.applyImpulse(%Imppos,vectorScale(%vec,$DTank::TurnForce * %obj.skill));
|
|
}
|
|
}
|
|
%obj.applyImpulse(%pos,vectorScale(%obj.getForwardVector(),$DTank::ForwardForce));
|
|
schedule(100, 0, "DTankGroundCombat",%obj,%target,%Trglist);
|
|
}
|
|
|
|
function DTankAACombat(%obj, %target, %Trglist){
|
|
if(!isObject(%obj))
|
|
return;
|
|
if(!isObject(%target)){
|
|
%obj.turretobject.setImageTrigger(2,false);
|
|
%obj.firing = "";
|
|
if(%TrgList){
|
|
%target = firstWord(%Trglist);
|
|
%trglist = getWords(%trglist,1,4);
|
|
}
|
|
else{
|
|
DTankScanTargets(%obj);
|
|
return;
|
|
}
|
|
}
|
|
%pos = %obj.getPosition();
|
|
%tpos = %target.getPosition();
|
|
if(vectorDist(%pos,%tpos) < 750){
|
|
if(!%obj.firing){
|
|
%obj.firing = 1;
|
|
%obj.turretobject.setTargetObject(%Target);
|
|
%obj.turretobject.aquireTime = getSimTime();
|
|
%obj.turretobject.setImageTrigger(2,true);
|
|
}
|
|
}
|
|
else if(vectorDist(%pos,%tpos) > 2000){
|
|
if(%obj.firing){
|
|
%obj.firing = "";
|
|
%obj.turretobject.setImageTrigger(2,false);
|
|
}
|
|
%target = "";
|
|
}
|
|
schedule(100, 0, "DTankAACombat",%obj,%target,%Trglist);
|
|
}
|
|
|
|
function DTankInfCombat(%obj, %target, %Trglist){
|
|
if(!isObject(%obj))
|
|
return;
|
|
if(!isObject(%target) || %target.getState() $= "dead"){
|
|
%obj.turretobject.setImageTrigger(3,false);
|
|
%obj.firing = "";
|
|
if(%TrgList){
|
|
%target = firstWord(%Trglist);
|
|
%trglist = getWords(%trglist,1,4);
|
|
}
|
|
else{
|
|
DTankScanTargets(%obj);
|
|
return;
|
|
}
|
|
}
|
|
%pos = %obj.getPosition();
|
|
%tpos = %target.getPosition();
|
|
%frdvec = vectorNormalize(getWords(%obj.getForwardVector(),0,1) SPC "0");
|
|
%chkvec = vectorSub(%tpos,%pos);
|
|
%chkvec = vectorNormalize(getWords(%chkvec,0,1) SPC "0");
|
|
%turnvec = vectorsub(%chkvec,%frdvec);
|
|
%vecdif = vectorlen(%turnvec);
|
|
if(vectorDist(%pos,%tpos) > 2000){
|
|
if(%obj.firing){
|
|
%obj.firing = "";
|
|
%obj.turret.setImageTrigger(3,false);
|
|
}
|
|
%target = "";
|
|
}
|
|
else if(vectorDist(%pos,%tpos) > 300){
|
|
if(%vecdif >= "0.1"){
|
|
%vec = vectorCross(%turnvec, %frdvec);
|
|
%vec = vectorNormalize(vectorCross(%obj.getForwardVector(), %vec));
|
|
%Imppos = vectorAdd(%pos,%obj.getForwardVector());
|
|
%obj.applyImpulse(%Imppos,vectorScale(%vec,$DTank::TurnForce * %obj.skill));
|
|
}
|
|
}
|
|
else{
|
|
if(!%obj.firing){
|
|
%obj.firing = 1;
|
|
%obj.turretobject.firetype = 1;
|
|
%obj.turretobject.setTargetObject(%Target);
|
|
%obj.turretobject.aquireTime = getSimTime();
|
|
%obj.turretobject.setImageTrigger(3,true);
|
|
}
|
|
if(vectorDist(%pos,%tpos) < 100){
|
|
if(%vecdif <= "1.6"){
|
|
%vec = vectorCross(%turnvec, %frdvec);
|
|
%vec = vectorNormalize(vectorCross(%obj.getForwardVector(), %vec));
|
|
%Imppos = vectorAdd(%pos,%obj.getForwardVector());
|
|
%obj.applyImpulse(%Imppos,vectorScale(%vec,$DTank::TurnForce * %obj.skill * "-1"));
|
|
}
|
|
}
|
|
else {
|
|
if(%vecdif < "1.2" || %vecdif >= "1.6"){
|
|
%Tvec1 = vectorNormalize(vectorcross(%chkvec,"0 0 1"));
|
|
%Tvec2 = vectorScale(%Tvec1,-1);
|
|
if(vectordist(%frdvec,%Tvec1) < vectorDist(%frdvec,%Tvec2))
|
|
%tovec = vectorSub(%Tvec1,%frdvec);
|
|
else
|
|
%tovec = vectorSub(%Tvec2,%frdvec);
|
|
%vec = vectorCross(%Tvec2, %frdvec);
|
|
%vec = vectorNormalize(vectorCross(%obj.getForwardVector(), %vec));
|
|
%Imppos = vectorAdd(%pos,%obj.getForwardVector());
|
|
%obj.applyImpulse(%Imppos,vectorScale(%vec,$DTank::TurnForce * %obj.skill));
|
|
}
|
|
}
|
|
}
|
|
%obj.applyImpulse(%pos,vectorScale(%obj.getForwardVector(),$DTank::ForwardForce));
|
|
schedule(100, 0, "DTankInfCombat",%obj,%target,%Trglist);
|
|
} |