construction-mod/scripts/MTC_ai.cs
2025-06-05 12:37:16 +02:00

1228 lines
28 KiB
C#

$MtcSuperRange = 0;
$MtcMaxAmmo["flare","light"] = 8;
$MtcMaxAmmo["flare","medium"] = 10;
$MtcMaxAmmo["flare","heavy"] = 0;
$MtcMaxAmmo["flash","light"] = 5;
$MtcMaxAmmo["flash","medium"] = 8;
$MtcMaxAmmo["flash","heavy"] = 0;
$MtcMaxAmmo["cloak","light"] = 160;
$MtcMaxAmmo["cloak","medium"] = 120;
$MtcMaxAmmo["cloak","heavy"] = 0;
$MtcMaxAmmo["mine","light"] = 4;
$MtcMaxAmmo["mine","medium"] = 6;
$MtcMaxAmmo["mine","heavy"] = 20;
$MtcDamageRun["light"] = 0.5;
$MtcDamageRun["medium"] = 0.55;
$MtcDamageRun["heavy"] = 0.75;
/////////////////////////////////////////////
///////////////[[Part1]]/////////////////////
/////////////////////////////////////////////
//Initialisation runs
function Item::Initialize(%obj)
{
//echo("Initialize");
///Arm ourselfes if we need to.
if (!IsObject(%obj.turret) || %obj.weapon $= "")
%obj.Arm();
//Starting supplies
%size = $mtcWeaponSize[%obj.weapon];
%obj.ammo["mine"] = $MtcMaxAmmo["mine",%size] * getRandom();
%obj.ammo["Cloak"] =$MtcMaxAmmo["cloak",%size] * getRandom();
%obj.ammo["flare"] =$MtcMaxAmmo["flare",%size] * getRandom();
%obj.ammo["flash"] =$MtcMaxAmmo["flash",%size] * getRandom();
//Set best attack patern
%obj.SetPatern();
//Set inventory loop
if (!%obj.invloop)
%obj.invloop();
//Set orders and run them
%obj.evaluate();
}
function Item::SetPatern(%obj)
{
//echo("setPatern");
///
/// sensors //// static /// turret /// gen
///
%obj.maxdist = 500; //Standart set for now
%obj.noacloak = 1; //Standart off
%obj.nocloak = 0;
if ($mtcWeaponSize[%obj.weapon] $= "light")
{
}
else if ($mtcWeaponSize[%obj.weapon] $= "medium")
{
%obj.movemod = -0.25;
}
else if ($mtcWeaponSize[%obj.weapon] $= "heavy")
{
%obj.nofly = 1;
%obj.movemod = 0.5;
%obj.nocloak = 1;
}
if (%obj.weapon $= "chain")
{
%obj.patern = "attack";
%obj.mindist = 20;
%obj.meddist = 50;
%obj.preftargets = "nturret lsensor ustatic astatic";
%obj.preftargetslack = 100;
}
else if (%obj.weapon $= "plasma")
{
%obj.patern = "attack";
%obj.mindist = 5;
%obj.meddist = 50;
%obj.preftargets = "lsensor lturret ustatic";
%obj.preftargetslack = 50;
%obj.movemod = -0.25;
%obj.noacloak = 0;
}
else if (%obj.weapon $= "Fusion")
{
%obj.patern = "attack";
%obj.mindist = 20;
%obj.meddist = 80;
%obj.preftargets = "agen astatic aturret";
%obj.preftargetslack = 150;
}
else if (%obj.weapon $= "nerf")
{
%obj.patern = "attack";
%obj.mindist = 5;
%obj.meddist = 20;
%obj.preftargets = "aplayer";
%obj.preftargetslack = 200;
}
else if (%obj.weapon $= "disc")
{
%obj.patern = "attack";
%obj.mindist = 15;
%obj.meddist = 200;
%obj.preftargets = "nturret lsensor aplayer";
%obj.preftargetslack = 50;
}
else if (%obj.weapon $= "blaster")
{
%obj.patern = "attack";
%obj.mindist = 5;
%obj.meddist = 50;
%obj.preftargets = "lsensor lturret nturret agen";
%obj.preftargetslack = 50;
%obj.noacloak = 0;
}
else if (%obj.weapon $= "target")
{
%obj.patern = "range";
%obj.mindist = 25;
%obj.meddist = 200;
%obj.preftargets = "aturret agen";
%obj.preftargetslack = 50;
}
else if (%obj.weapon $= "grenade")
{
%obj.patern = "range";
%obj.mindist = 30;
%obj.meddist = 200;
%obj.preftargets = "ustatic lsensor agen";
%obj.preftargetslack = 50;
}
else if (%obj.weapon $= "laser")
{
%obj.patern = "range";
%obj.mindist = 20;
%obj.meddist = 200;
%obj.preftargets = "aplayer lsensor";
%obj.preftargetslack = 50;
}
else if (%obj.weapon $= "missile")
{
%obj.patern = "range";
%obj.mindist = 50;
%obj.meddist = 200;
%obj.preftargets = "aturret aplayer avehicle";
%obj.preftargetslack = 75;
}
else if (%obj.weapon $= "swarmdisc")
{
%obj.patern = "range";
%obj.mindist = 50;
%obj.meddist = 200;
%obj.preftargets = "aturret aplayer avehicle";
%obj.preftargetslack = 75;
}
else if (%obj.weapon $= "ionmissile")
{
%obj.patern = "range";
%obj.mindist = 100;
%obj.meddist = 200;
%obj.preftargets = "pstatic pturret pgen";
%obj.preftargetslack = 1000;
}
else if (%obj.weapon $= "ionbeam")
{
%obj.patern = "range";
%obj.mindist = 50;
%obj.meddist = 200;
%obj.preftargets = "pstatic pturret pgen";
%obj.preftargetslack = 1000;
}
else if (%obj.weapon $= "mortar")
{
%obj.patern = "range";
%obj.mindist = 50;
%obj.meddist = 300;
%obj.preftargets = "agen astatic aturret";
%obj.preftargetslack = 50;
}
else if (%obj.weapon $= "tractor")
{
%obj.patern = "range";
%obj.mindist = 50;
%obj.meddist = 100;
%obj.preftargets = "aplayer avehicle";
%obj.preftargetslack = 500;
}
else
{
%obj.patern = "attack";
%obj.mindist = 5;
%obj.meddist = 20;
%obj.preftargets = "aplayer";
%obj.preftargetslack = 50;
}
}
/////////////////////////////////////////////
///////////////[[Part2]]/////////////////////
/////////////////////////////////////////////
//Loops
function Item::invloop(%obj)
{
//echo("invloop");
Cancel(%obj.invloop);
if (!%obj.nosuply)
{
%size = $mtcWeaponSize[%obj.weapon];
%obj.ammo["mine"] = limit(%obj.ammo["mine"] + 1,0, $MtcMaxAmmo["mine",%size]);
%obj.ammo["cloak"] = limit(%obj.ammo["cloak"] + 30,0, $MtcMaxAmmo["cloak",%size]);
%obj.ammo["flare"] = limit(%obj.ammo["flare"] + 1,0, $MtcMaxAmmo["flare",%size]);
%obj.ammo["flash"] = limit(%obj.ammo["flash"] + 1,0, $MtcMaxAmmo["flash",%size]);
}
if (!%obj.noaggression)
%obj.aggression = limit(%obj.aggression + getRandom()-0.5,0,10);
%obj.notify("ammo");
//Gets his stuff every minute.
%obj.invloop = %obj.schedule(60000,"invloop");
}
function Item::evaluate(%obj)
{
%obj.lastevaltime = getSimTime();
Cancel(%obj.evalloop);
%obj.sound("think");
if (%obj.order !$= "")
{
//Attack
if (%obj.order $= "attack")
{
if (%obj.ValidTarget() || %obj.targetrun < 6)
{
%obj.targetrun++;
///LETS GO ATTACK
%obj.attackrun(); //Only attack the same target for 1 minute
%obj.notify("attack");
}
else
{
%obj.target = %obj.NewTarget();
if (%obj.ValidTarget())
{
///STOP ATTACKING
%obj.order = "";
}
else
{
//Go attack the next run
%obj.targetrun = "";
}
}
}
//Flee
else if (%obj.order $= "flee")
{
if (%target = %obj.gotThreat() !$= "")
{
///LETS GO FLEE
%obj.target = %target;
%obj.fleerun();
%obj.notify("flee");
}
else
{
//STOP FLEEING
%obj.order = "";
}
}
//Roam
else if (%obj.order $= "roam")
{
//Still no valid target?
%target = %obj.ClosestTarget();
if (!%obj.ValidTarget(%obj.NewTarget()))
{
///LETS GO ROAM
//%obj.target = %target;
%obj.roamrun();
%obj.notify("roam");
}
else
{
///STOP ROAMING
%obj.order = "";
}
}
//Repair
else if (%obj.order $= "repair")
{
//Are we still damaged?
if (%obj.turret.getDamagePct() > 0.1)
{
//Are there enemies nearby?
if (%obj.gotThreat())
{
if (%obj.needflee())
{
//STOP REPAIRING
%obj.order = "";
}
else
{
//STOP REPAIRING
%obj.order = "";
}
}
else
{
///LETS GO REPAIR
%obj.repairrun();
%obj.notify("repair");
}
}
else
{
///STOP REPAIRING
%obj.order = "";
}
}
}
///So we didn't have any orders?
if (%obj.order $= "")
{
///Are we hurt??
if (%obj.needflee())
{
///Do we need to run?
if (%obj.gotThreat())
{
%obj.order = "flee";
%rechecktime = 450;
Cancel(%obj.mainrun);
}
else
{
%obj.order = "repair";
%rechecktime = 450;
Cancel(%obj.mainrun);
}
}
else
{
///Anyone to attack?
%obj.target = %obj.NewTarget();
if (!%obj.ValidTarget())
{
%obj.target= %obj.closestTarget();
%obj.order = "roam";
%rechecktime = 450;
Cancel(%obj.mainrun);
}
else
{
%obj.order = "attack";
%rechecktime = 450;
Cancel(%obj.mainrun);
}
}
}
if (!%rechecktime)
%rechecktime = 10000;
%obj.evalloop = %obj.schedule(%rechecktime,"evaluate");
}
function Item::Needflee(%obj)
{
%size = $mtcWeaponSize[%obj.weapon];
if (%obj.turret.getDamagePct() > $MtcDamageRun[%size])
return 1;
else if (%obj.ammo["flare"] < $MtcDamageRun[%size]*$MtcMaxAmmo["flare",%size] && $MtcMaxAmmo["flare",%size])
return 1;
return 0;
}
/////////////////////////////////////////////
///////////////[[Part3]]/////////////////////
/////////////////////////////////////////////
//Targeting
// Defined in scripts/ion.cs
//function GameBase::isEnemy(%obj,%target) {
// //echo("isenemy");
// if (!isObject(%obj) || !isObject(%target))
// return "";
// if (%obj.team != %target.team) ///Other teams default to enemy.
// return 1;
// if (%obj.getOwner().evil) {
// if (%obj.getOwner() != %target.client && %obj.getOwner() != %target.getOwner())
// return 1;
// }
// return "";
//}
function Item::gotThreat(%obj) //////Needs update.
{
//echo("gotThreat");
%target = closestTarget(%obj.getWorldboxCenter(),"aplayer pturret cvehile",%obj.maxdist,%obj);
if (GetWord(%target,1) < %obj.maxdist)
return GetWord(%target,0);
return "";
}
function Item::ValidTarget(%obj,%target) ///Needs update
{
if (!%target)
%target = %obj.target;
if (mtcCleantarget(%target))
{
if (%target == %obj.forcetarget())
return 1;
if (%obj.terdist(%target) < %obj.maxdist)
{
if (!(%target.getDataBlock().className $= "Armor" && %target.getState() $= "Dead"))
{
return 1;
}
}
}
return "";
}
//Can we as mtc get to this target?
function mtcCleantarget(%target)
{
//echo("mtcCleantarget");
//Only exsistant objects, no clients.
//No nonpowered forcefields.
//Only players,vehicles or stuff deployed ingame.
//Only stuff outside buildings or that sticks out.
%group = nameToID("MissionCleanup/Deployables");
if (%target && IsObject(%target) && !%target.player)
{
if (!(!%target.isPowered() && %target.isforcefield()))
{
if (%target.getType() & typelist("aplayer avehicle") || %group.isMember(%target))
{
%fstat = aboveground(%target.getworldboxcenter(),1,%obj);
%stat = GetWord(%fstat,0);
if(%stat $= "open" || %stat $= "roof" || %stat $= "shadow")
return 1;
else if (%target.seetop())
return 1;
}
}
}
return "";
}
function Item::NewTarget(%obj,%target)
{
//echo("NewTarget");
if (%obj.forcetarget())
return %obj.forcetarget();
%sugtarget = %target;
if (Change(%obj.aggression,5,10) && IsObject(%plyrtarget))
{
%target = closestTarget(%obj.getWorldboxCenter(),"aplayer cvehile","",%obj);
}
else
{
%preftarget = closestTarget(%obj.getWorldboxCenter(),%obj.preftargets,"",%obj);
%alttarget = closestTarget(%obj.getWorldboxCenter(),"aall","",%obj);
if (GetWord(%alttarget,1) > GetWord(%preftarget,1)- %obj.preftargetslack && IsObject(%preftarget))
{
%target = %preftarget;
}
else
{
%target = %alttarget;
}
}
if (!IsObject(%target))
%target = ClosestPlayer(%obj.getWorldBoxCenter(),"","",%obj);
return getWord(%target,0);
}
function Item::ClosestTarget(%obj)
{
//echo("closesttarget");
return closestTarget(%obj.getWorldBoxCenter(),"aall","",%obj);
}
function closestTarget(%location,%ftype,%range,%obj)
{
//echo("closesttarget");
%group = nameToID("MissionCleanup/Deployables");
if (%ftype $= "")
%ftype = aall;
if (!%range)
%range = 1000 + (100000* $MtcSuperRange);
%mask = typelist(%ftype);
InitContainerRadiusSearch(%location,%range,%mask);
while ((%target = ContainerSearchNext()) != 0)
{
if (mtcCleantarget(%target))
{
if (%target.onpreflist(%ftype) && (IsObject(%obj) && %obj.isEnemy(%target)))
return %target SPC containerSearchCurrRadDamageDist();
}
}
return "";
}
function Item::forcetarget(%obj)
{
//echo("forcetarget");
%target = %obj.forcetarget;
if (%target !$= "")
{
if (IsObject(%target.player))
return %target.player;
else if (%target.getClassname() !$= "GameConnection")
return %target;
}
%target = mtcgroup.forcetarget;
if (%target !$= "")
{
if (IsObject(%target.player))
return %target.player;
else if (%target.getClassname() !$= "GameConnection")
return %target;
}
return "";
}
/////////////////////////////////////////////
///////////////[[Part4]]/////////////////////
/////////////////////////////////////////////
//Actions
function Item::resetorders(%obj)
{
//echo("resetorders");
%obj.order = "";
Cancel(%obj.evalloop);
%obj.evalloop = %obj.schedule(450,"evaluate");
return"";
}
//GO ATTACK
function Item::attackrun(%obj)
{
//echo("attackrun");
Cancel(%obj.mainrun);
%obj.checkflare();
%obj.flaredelay(1);
if (!%obj.ValidTarget() || %obj.needflee())
{
return %obj.resetorders();
}
///Basic Information
%loc = %obj.getWorldboxCenter();
%target = %obj.target;
%tloc = %obj.target.getWorldboxCenter();
%line = VectorSub(%tloc,%loc);
%dir = VectorNormalize(%line);
%dist = VectorLen(%line);
///Movement patern
%obj.attackcloak = 0;
%obj.canfire("target");
if (%dist < %obj.mindist && !(%obj.forcetarget() && !%obj.nofly))
{
///Whoa we're too close
%obj.move(%tloc,"to",-0.6);
%obj.dodge = randomlev();
}
else if (%dist > %obj.mindist && %dist < %obj.meddist && !(%obj.forcetarget() && !%obj.nofly))
{
//perfect let's Guooo.
if (%obj.patern $= "attack")
{
///Lets make him dizzy
%obj.move(%tloc,"side",%obj.dodge*0.5);
}
else if (%obj.patern $= "range")
{
///Lets get a nice high spot
%obj.move(%tloc,"up",1);
}
else
{
///Oh sure.. I'l be dead in the water.
}
}
else if ((%dist > %objmeddist && %dist < %obj.maxdist) || (%obj.forcetarget() && !%obj.nofly))
{
//Damn he's too far
%obj.move(%tloc,"to",0.9);
%obj.dodge = randomlev();
if ((!%obj.noacloak) && !%obj.forcetarget() && %dist > %obj.meddist*1.2)
{
%obj.attackcloak = 1;
%obj.cloak(1);
}
}
else
{
//We're outa range.
%obj.move(%tloc,"to",0.5);
%obj.canfire();
if (!%obj.noacloak)
{
%obj.attackcloak = 1;
%obj.cloak(1);
}
}
if (!%obj.attackcloak)
%obj.cloak();
%obj.mainrun = %obj.schedule(500, "attackrun");
}
//GO FLEE
function Item::fleerun(%obj)
{
//echo("fleerun");
Cancel(%obj.mainrun);
%obj.checkflare();
%obj.flaredelay();
if (%target = %obj.gotThreat())
%obj.target = %target;
else if (%target = %obj.closestTarget())
%obj.target = %target;
else
{
//Omg there's noone near for miles
return %obj.resetorders();
}
///Basic Information
%loc = %obj.getWorldboxCenter();
%target = %obj.target;
%tloc = %obj.target.getWorldboxCenter();
%line = VectorSub(%tloc,%loc);
%dir = VectorNormalize(%line);
%dist = VectorLen(%line);
///Movement patern
%obj.canfire();
if (%dist < %obj.mindist)
{
//Whoa double time
%obj.move(%tloc,"to",-1.2);
%obj.cloak(1);
if (!%obj.cloaked)
%obj.canfire("target");
}
else if (%dist > %obj.mindst && %dist < %obj.meddist )
{
//Move move move
%obj.move(%tloc,"to",-1);
%obj.cloak(1);
%obj.Mine();
if (!%obj.cloaked)
%obj.canfire("target");
}
else if (%dist > %objmeddist && %dist < %obj.maxdist )
{
//Just a litle futher
%obj.target = %obj.closesttarget();
%obj.move(%tloc,"to",-0.8);
%obj.cloak(1);
}
else
{
%obj.target = %obj.closesttarget();
//Finally he's gone.
%obj.cloak(0);
}
%obj.mainrun = %obj.schedule(500, "fleerun");
}
//GO REPAIR
function Item::repairrun(%obj)
{
//echo("repairrun");
Cancel(%obj.mainrun);
Cancel(%obj.repairsch);
%obj.checkflare();
%obj.flaredelay();
if (%obj.gotThreat())
{
return %obj.resetorders();
}
%obj.cloak(1);
%obj.canfire();
createLifeEmitter(%obj.getWorldboxCenter(), ELFSparksEmitter, 450);
%size = $mtcWeaponSize[%obj.weapon];
%obj.ammo["flare"] = limit(%obj.ammo["flare"] + 1,0,$MtcMaxAmmo["flare",%size]);
%obj.turret.setRepairRate(0.004);
%obj.repairsch = %obj.turret.schedule(450,"setRepairRate",0);
%obj.mainrun = %obj.schedule(500,"repairrun");
}
//GO ROAM
function Item::roamrun(%obj)
{
//echo("roamrun");
Cancel(%obj.mainrun);
%obj.roamtime = %obj.roamtime - 1;
//%obj.target = %obj.NewTarget();
//%obj.ValidTarget()
if ( %obj.needflee())
{
return %obj.resetorders();
}
%obj.checkflare();
%obj.flaredelay();
if (%obj.roamtime < 0)
{
%obj.totalroam++;
%obj.roamdir = getRandom();
%obj.roamtime = getRandom() * 200+50;
if (%obj.totalroam > 20)
{
%obj.totalroam = 0;
%obj.telleport(getTerrainHeight2("0 0 0","0 0 -1"));
}
}
%obj.cloak();
%obj.canfire();
///This will make the mtc move directly towards the closest target when he's angry
///And all directions when he's not.
if (IsObject(%obj.target) && %obj.dist(%obj.target) < %obj.maxdist)
%obj.moveangle = RandomLev()*($Pi + $Pi*getRandom());
else
%obj.moveangle = %obj.roamdir*(((1-(%obj.aggression /10))* 2* $Pi) - $Pi);
if (MtcCleanTarget(%obj.target))
{
%location = %obj.target.getWorldBoxCenter();
if ((%obj.dist(%obj.target)/%obj.altdist(%obj.target))<1.5)
%obj.moveangle = 0;
}
else
{
%location = VectorAdd(mCos(%obj.Moveangle)*100 SPC mSin(%obj.moveangle)*100 SPC 0,%obj.getWorldBoxCenter());
}
%obj.move(%location,"angle",0.8);
%obj.mainrun = %obj.schedule(500, "roamrun");
}
//Go Move Target (avioding threats)
function Item::moveTrun(%obj)
{
//echo("moverun");
Cancel(%obj.mainrun);
%obj.checkflare();
if (!mtcCleanTarget(%obj.target))
{
%obj.order = "";
Cancel(%obj.evalloop);
%obj.evalloop = %obj.schedule(450,"evaluate");
}
///Basic Information
%loc = %obj.getWorldboxCenter();
%target = %obj.target;
%tloc = %obj.target.getWorldboxCenter();
%line = VectorSub(%tloc,%loc);
%dir = VectorNormalize(%line);
%dist = VectorLen(%line);
if (%threat = %obj.gotThreat())
{
%trloc = %Threat.getWorldBoxCenter();
%trdir = %obj.dir(%threat);
%angle = VectorAngle(%trdir,%dir);
%avoiddir = VectorCross(VectorCross(%trdir,%dir),%trdir);
}
%obj.canfire("");
if (%dist < %obj.mindist)
{
%obj.order = "";
Cancel(%obj.evalloop);
%obj.evalloop = %obj.schedule(450,"evaluate");
}
else
{
if (%angle > $Pi)
%obj.move(%tloc,"to",1);
else
{
%obj.movedir = %avoiddir;
%obj.move(%trloc,"dir",1);
}
}
%obj.mainrun = %obj.schedule(500, "moveTrun");
}
//Basic Moving
function Item::move(%obj,%location,%mdir,%speed)
{
//echo("move");
if (%obj.nomove)
return "";
%obj.evalpos++;
//Information
%selfloc = %obj.getWorldBoxCenter();
%targetloc = %location;
%targetline = Vectorsub(%targetloc,%selfloc);
%targetdir = VectorNormalize(%targetline);
%targetdist = VectorLen(%targetline);
%altdist = GetWord(%targetline,2);
if (%obj.evalpos > 10)
{
%obj.FixHeight();
%movedist = VectorDist(%obj.getWorldboxCenter(),%obj.lastlocation);
if ((%movedist < 5 && %mdir !$= "up" && %targetdist > %obj.meddist) || (%movedist < 1 && %targetdist > %obj.mindist) || %movedist < 0.1)
{
%obj.freeforce = %obj.freeforce + 10;
if (%obj.freeforce * %speed < %targetdist)
%dir = VectorScale(%targetdir,%obj.freeforce*%speed);
else
%dir = VectorScale(%targetdir,%targetdist - 2);
%newpos = getTerrainHeight2(VectorAdd(%obj.getWorldboxCenter(),%dir),"0 0 -1");
%obj.telleport(%newpos); //Break free.
%obj.movepower = 60;
}
else if (%movedist < 20)
{
%obj.movepower = Limit(%obj.movepower+20,0,1000);
%obj.freeforce = 10;
}
else
{
%obj.movepower = 60;
%obj.freeforce = 10;
}
%obj.lastlocation = %obj.getWorldboxCenter();
%obj.evalpos = 0;
}
if (%targetdist > 2000 && %obj.order !$= "roam")
{
%dir = VectorScale(%targetdir,%targetdist-500);
%newpos = VectorAdd(%obj.getWorldboxCenter(),%dir);
if ((%targetdist/%altdist)>1.5)
%newpos = getTerrainHeight2(%newpos,"0 0 -1");
%obj.telleport(%newpos); //Get way closer.
}
else if (%targetdist > 4000 && %obj.order $= "roam" && %disabled)
{
%dir = VectorScale(%targetdir,%targetdist-3000);
%newpos = VectorAdd(%obj.getWorldboxCenter(),%dir);
if ((%targetdist/%altdist)>1.5)
%newpos = getTerrainHeight2(%newpos,"0 0 -1");
%obj.telleport(%newpos); //Get some closer.
}
%offset = VectorScale(VectorCross(VectorCross("0 0 1",%targetdir),%targetdir),20);
%res = containerRayCast(%obj.getWorldboxCenter(), VectorAdd(%obj.getWorldboxCenter(),%offset), $TypeMasks::TerrainObjectType, %obj.turret);
if (%res)
{
%nrm = normalFromRaycast(%res);
}
else
{
%nrm = "0 0 1";
}
%dir = %targetdir;
if (%mdir $= "to") // Towards/from
%movedir = VectorCross(VectorCross(%nrm,%dir),%nrm);
else if (%mdir $= "side") //Sideways
%movedir = VectorCross(%nrm,%dir);
else if (%mdir $= "up") //Up the mountain
{
if (vAbs(floorvec(%nrm,100)) $= "0 0 1")
%movedir = VectorCross(%nrm,%dir);
else
%movedir = VectorCross(VectorCross(%nrm,"0 0 1"),%nrm);
}
else if (%mdir $= "angle") //Certain angle away from target.
{
%movedir1 = VectorScale(VectorCross(VectorCross(%nrm,%dir),%nrm),MCos(%obj.moveangle));
%movedir2 = VectorScale(VectorCross(%nrm,%dir),MSin(%obj.moveangle));
%movedir = VectorAdd(%movedir1,%movedir2);
}
else if (%mdir $= "dir")
{
%movedir = VectorCross(VectorCross(%nrm,%obj.movedir),%nrm);
}
//Flying
%targetplace = GetWord(aboveground(%targetloc,1,0),0);
if (((%obj.wasflying && (%targetdist/%altdist)<2)|| %obj.forcetarget() || ((%targetdist/%altdist)<1.5 && %targetdist > 200)) && %obj.order $= "attack" && !%obj.nofly && (%targetplace $= "open"|| %targetplace $="roof"))
{
%speed = mCeil(%targetdist/100)+0.5;
%nrm = "0 0 1";
%movedir = VectorNormalize(VectorAdd(VectorAdd(VectorCross(VectorCross(%nrm,%dir),%nrm),VectorCross(%nrm,%dir)),"0 0" SPC Lev(GetWord(%targetdir,2))/2));
%obj.wasflying = 1;
%obj.flaredelay(1);
}
else if (VectorDist(getTerrainHeight2(pos(%obj),"0 0 -1"),pos(%obj))>50)
%movedir = VectorAdd(%movedir,"0 0" SPC GetWord(%targetdir,2));
else
%obj.wasflying = 0;
%pulse = Limit(1 * %obj.movepower * %speed*(1+%obj.movemod),-1000,1000);
//Floating
if (%disabled && Isobject(Water) )
{
%surface = GetWords(pos(%obj),0,1) SPC (GetWord(Water.getTransform(),2)+GetWord(Water.getScale(),2))+2;
if ((GetWord(pos(%obj),2)-GetWord(%surface,2))<2)
{
%res2 = containerRayCast(%surface,pos(%obj),-1, %obj.turret);
////echo(%res2.getClassname());
if (%res2 && %res2.getClassname() $= "Waterblock")
{
//%movedir = VectorAdd(%movedir,"0 0" SPC GetWord(%targetdir,2));
//%obj.setTransform(%surface);
////echo("float");
}
}
}
%obj.sound("move");
%obj.Jet(500);
%movedir = VectorNormalize(%movedir);
%obj.applyImpulse(%obj.getWorldboxCenter(), VectorScale(%movedir,%pulse));
//%obj.setRotation(fullrot("0 0 1",%movedir));
}
function Item::flaredelay(%obj,%set)
{
if (%set)
%obj.flaredelay++;
else
%obj.flaredelay = 0;
}
function Item::checkflare(%obj)
{
//echo("checkflare");
%size = $mtcWeaponSize[%obj.weapon];
if (%size $= "heavy")
%obj.turret.signature.PointDefLaser();
else if (%obj.turret.signature.homingcount)
{
%delay = Limit(%obj.flaredelay,0,10)*getRandom()*1000+100;
if (getRandom(1))
%obj.schedule(500+getRandom()*500+%delay,"flare");
}
}
function Item::FixHeight(%obj)
{
//echo("fixheight");
%pos = getTerrainHeight2(%obj.getWorldboxCenter(),"0 0 -1");
if (GetWord(%obj.getWorldboxCenter(),2) < GetWord(%pos,2))
{
%obj.telleport(%pos);
}
}
function Gamebase::hastag(%obj,%tag)
{
//echo("hastag");
//Sizes
if (%tag $= "l" || %tag $= "m" || %tag $= "h")
{
%maxdamage= %obj.getDatablock().maxdamage;
if (%tag $= "l" && %maxdamage <= 1)
return 1;
else if (%tag $= "m" && %maxdamage > 1)
return 1;
else if (%tag $= "h" && %maxdamage > 2)
return 1;
}
//Powered
else if (%tag $= "p" || %tag $= "n")
{
%power = %obj.isPowered();
if (%tag $= "p" && %power)
return 1;
else if (%tag $= "n" && !%power)
return 1;
}
//Shielded
else if (%tag $= "s" || %tag $= "u")
{
%shield = (%obj.getDataBlock().isShielded == 1 && %obj.getEnergyLevel() > 0);
if (%tag $= "s" && %shield)
return 1;
if (%tag $= "u" && !%shield)
return 1;
}
//Controlled
else if (%tag $= "c" || %tag $= "e")
{
%Piloted = !((%obj.getType() & $TypeMasks::VehicleObjectType) || %obj.getPilot());
if (%tag $= "c" && %piloted)
return 1;
if (%tag $= "e" && !%piloted)
return 1;
}
//Everything ;)
else if (%tag $= "a")
return 1;
return "";
}
function gettype(%type)
{
//echo("gettype");
if (%type $= "turret")
return $TypeMasks::TurretObjectType;
else if (%type $= "sensor")
return $TypeMasks::SensorObjectType;
else if (%type $= "gen")
return $TypeMasks::GeneratorObjectType;
else if (%type $= "static")
return $TypeMasks::StaticShapeObjectType;
else if (%type $= "player")
return $TypeMasks::PlayerObjectType;
else if (%type $= "vehicle")
return $TypeMasks::VehicleObjectType;
else if (%type $= "forcefield")
return $TypeMasks::ForceFieldObjectType;
else if (%type $= "all")
return $TypeMasks::StaticShapeObjectType | $TypeMasks::PlayerObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::ForceFieldObjectType;
else
return 0;
}
function typelist(%ftype)
{
//echo("typelist");
for(%tt = 0; %tt< GetWordCount(%ftype); %tt++ )
{
%part = getWord(%ftype,%tt);
%type = getSubStr(%part,1,strLen(%part));
%list = %list | gettype(%type);
}
return %list;
}
function Gamebase::onpreflist(%obj,%ftype)
{
//echo("onpreftlist");
for(%tt = 0; %tt< GetWordCount(%ftype); %tt++ )
{
%part = getWord(%ftype,%tt);
%tag = getSubStr(%part,0,1);
%type = getSubStr(%part,1,strLen(%part));
if (%obj.getType() & gettype(%type) && %obj.hastag(%tag))
return 1;
}
return "";
}
function AssesBase(%location)
{
//echo("assesbase");
InitContainerRadiusSearch(%location,200,-1);
while ((%target = ContainerSearchNext()) != 0)
{
if (%target.getType() & $TypeMasks::TurretObjectType && %target.hastag("s"))
%turretCount++;
if (%target.getType() & $TypeMasks::InteriorObjectType)
%interiorCount++;
if (%target.getType() & $TypeMasks::StaticShapeObjectType)
{
%staticCount++;
%height = %height + GetWord(AboveGround(pos(%target),1),1);
}
if (%target.getType() & $TypeMasks::PlayerObjectType)
%playerCount++;
%count=%count++;
}
%height = %height/%staticCount;
//echo(%count);
//echo(%height);
//echo(%interiorcount);
//echo(%turretcount);
//echo(%staticCount);
//echo(%playercount);
}
function Vehicle::getpilot(%obj) ///Needs update to remotecontroll
{
%pilot = %obj.getMountNodeObject(0);
%client = %pilot.client;
return %client;
}
function Shapebase::dir(%obj,%target)
{
%pos1 = %obj.getWorldboxCenter();
%pos2 = %target.getWorldboxCenter();
return VectorNormalize(VectorSub(%pos2,%pos1));
}
function Shapebase::dist(%obj,%target)
{
%pos1 = %obj.getWorldboxCenter();
%pos2 = %target.getWorldboxCenter();
return VectorDist(%pos1,%pos2);
}
function Shapebase::terdist(%obj,%target)
{
%pos1 = %obj.getWorldboxCenter();
%pos2 = %target.getWorldboxCenter();
return VectorDist(GetWords(%pos1,0,1),GetWords(%pos2,0,1));
}
function Shapebase::altdist(%obj,%target)
{
%pos1 = %obj.getWorldboxCenter();
%pos2 = %target.getWorldboxCenter();
return VectorDist(GetWord(%pos1,2),GetWord(%pos2,2));
}