package { import flash.display.MovieClip; import flash.events.Event; import flash.geom.Point; import flash.utils.Timer; import flash.events.TimerEvent; public class AIShip extends Ship//------------------------------OLD CLASS SAVED AS BACKUP------------------------------ { private var id:int; private var sector:Sector; private var target:Ship; private var mainWep:Object; private var fireCounter:int = 0; private var behaviorCounter:int = 0; private var behaviorTimer:Timer; private var behavior:Array = new Array(); private var behaviorDice:Number = -1; private var aggro_gain:int = 800; private var aggro_loose:int = 800; public function AIShip($ID:int, $coords:Point, $rotation:Number, $allegience:int, $sector:Sector, $properties:Object, $mainWep:Object) { id = $ID; sector = $sector; mainWep = $mainWep; super($coords, $rotation, $sector, $properties, $allegience); behavior["fleeing"] = false; //loop addEventListener(Event.ENTER_FRAME, loop); } private function loop($e:Event):void { onNewCoords(); move(); deathCheck(); //remove target if it's dead if (target && target.HP <= 0) target = null; if (target && isTargetInRange())//we have a target and it's in range { //turn towards target and fire if no other behavior is set if (!behaviorsActive())//do NOT do any of this if you are engaging in a behavior { turnTowardTarget(); //follow target if it's farther away than 150px, otherwise slowDown if (calcDist(target.x, target.y) > 150) speedUp(); else Speed -= BreakSpeed; } } else//we don't have a target { lookForTarget();//look for a target and set one if it's in range Speed -= BreakSpeed; stopTurning(); } if (++behaviorCounter >= 40) { behaviorCounter = 0; makeBehaviorDecision(); } if (++fireCounter >= (40 / mainWep.rof))//40 = the framerate fireCounter = 0; } ///runs once every second to simulate puny humans slow brains private function makeBehaviorDescision() { //30% chance that this ship will reset target if the target is the player //if there is no other ship around, the player will become the target again if (target && target.ID == -1 && Math.random() <= .3) target = null; } private function speedUp() { Speed += SpeedAcc; } public override function projectileHit($damage:Number):void { //1/3 chance that this ship will flee (evade the shooter for 2 s.) when hit if (!behavior["fleeing"]) flee_start(); super.projectileHit($damage); } ///Flies off in a random direction and resets target private function flee_start() { behavior["fleeing"] = true; target = null; behaviorTimer = new Timer(25); behaviorTimer.addEventListener(TimerEvent.TIMER, flee, false, 0, true);//runs flee() once every frame behaviorTimer.addEventListener(TimerEvent.TIMER_COMPLETE, flee_end, false, 0, true);//when timer is done, run flee_end() behaviorTimer.repeatCount = 80;//80 * 25 = 2000ms behaviorTimer.start(); } private function flee($e:Event) { speedUp(); if(behaviorDice < 0) behaviorDice = Math.random(); rotation += (behaviorDice - .5) * TorqueMax * TorqueRate; } public function flee_end($e:Event) { behaviorTimer.removeEventListener(TimerEvent.TIMER, flee_end); behavior["fleeing"] = false; behaviorDice = -1; } private function lookForTarget():void { var ships:Array = sector.getShips(); for (var i:int = 0; i < ships.length; i++ ) { if (ships[i] && ships[i].Allegiance != Allegiance) { var distance:Number = calcDist(ships[i].x, ships[i].y); if (distance < aggro_gain) { target = ships[i]; i = ships.length; } } } } private function isTargetInRange():Boolean { if (calcDist(target.x, target.y) > aggro_loose) { target = null; return false; } else { return true; } } private function behaviorsActive():Boolean { var temp:Boolean = false; for each(var b:Boolean in behavior) { if (b) temp = true; } return temp; } private function turnTowardTarget():void { var degrees = Math.atan2(target.x - x, target.y - y) * (180 / Math.PI); degrees = -degrees + 180; degrees = Math.round(degrees); //0 speed = 1, full speed = 0.5 //TorqueRate controls how fast the ship can turn, at 0% speed it turns at full rate, at 100% speed it turns at 50% of TorqueSpeed //converts values above 180 to between -1 and -180 if (degrees > 180) degrees = -(360 - degrees); //turns this ship the correct way towards the target if ((degrees < 0 && rotation < 0) || (degrees >= 0 && rotation >= 0))//target is on the same half-circle-side of the ships angle { if (degrees > rotation + (TorqueMax)) { turnRight(); } else if (degrees < rotation - (TorqueMax)) { turnLeft(); } else { stopTurning(); fire(); } } else//target is on the opposite right/left half-circle-side of what this ship is currently pointing at { var distCW:Number; var distCCW:Number; //calculate wether clock-wise or counter-clockwise or the shortest way to turn if (rotation < 0)//left to right { distCW = Math.abs(rotation - degrees); distCCW = (180 - Math.abs(rotation)) + (180 - degrees); } else//right to left { distCW = (180 - Math.abs(rotation)) + (180 - rotation);//this line is totally wrong but produces correct results somehow distCCW = Math.abs(rotation - degrees); } if (distCW > distCCW) turnLeft(); else turnRight(); } //trace("speed: " + Speed + " torqueSpeed: " + TorqueSpeed + " TorqueRate: " + TorqueRate); } private function turnLeft() { TorqueSpeed -= TorqueAcc; } private function turnRight() { TorqueSpeed += TorqueAcc; } private function stopTurning() { if (TorqueSpeed > (TorqueMax * TorqueRate) || TorqueSpeed < (TorqueMax * TorqueRate)) TorqueSpeed *= .5; } private function fire():void { if (!fireCounter)//fireCounter is 0 { var temp:Projectile = new Projectile(Speed, rotation, mainWep, getSector, this); getSector.addChildAt(temp, 0); } } public override function destroy():void { HP = 0; Dying = true; target = null; getSector.removeAIShip(id); removeEventListener(Event.ENTER_FRAME, loop); super.destroy(); } //--------------------------------------------set/get-------------------------------------------- public override function get ID():int { return id; } } }