--Return the direction (in degrees) to a point. function point_direction(x1,y1,x2,y2) return math.deg(math.atan2((y1-y2),(x1-x2))); end --Return the distance to a point. function point_distance(x1,y1,x2,y2) return (math.sqrt(math.pow(x2-x1,2)+math.pow(y2-y1,2))); end --Return the x coordinate of a point dist pixels away in direction ang. function lengthdir_x(dist,ang) return dist * math.cos(ang*math.pi/180); end --Return the y coordinate of a point dist pixels away in direction ang. function lengthdir_y(dist,ang) return dist * math.sin(ang*math.pi/180); end function GravitateMovableObjectB(object,pointx,pointy,grav,rotate,maxrange) local dir = point_direction(object.Pos.X,object.Pos.Y,pointx,pointy); if rotate == 1 then object.RotAngle = -dir; end local mod = (-point_distance(object.Pos.X,object.Pos.Y,pointx,pointy)/maxrange)+1; if mod < 0 then mod = 0; end if object.PinStrength == 0 then object.Vel = Vector(object.Vel.X - lengthdir_x(grav*mod,dir),object.Vel.Y - lengthdir_y(grav*mod,dir)); end end function Create(self) --How long this has been going on for. self.scriptTimer = Timer(); --Pin the ship in the sky. self.PinStrength = 10000; --List of letters. self.letters = { "A", "B", "C", "D", "E" }; --How strong the wind should be. self.wind = (math.random() - 0.5) / 5; --Whether the big crack as happened yet. self.hascracked = false; --Whether the explosion has happened yet. self.hasexploded = false; --Where to land. self.landspot = SceneMan:MovePointToGround(self.Pos,0,0); --Whether the chosen actor is vincible or not. self.vincible = true; --Play the song. AudioMan:StopMusic(); AudioMan:PlayMusic("ComingOfGod.rte/Rain_Theme.ogg",0,100); AudioMan:ClearMusicQueue(); AudioMan:QueueMusicStream("ComingOfGod.rte/Ending Rain.wav"); --The music music volume before changes. self.oldvol = AudioMan.MusicVolume; end function Update(self) --Get the actor info. if self.ctype == nil then --Find the actor. local curdist = 50; local found = nil; for actor in MovableMan.Actors do local avgx = actor.Pos.X - self.Pos.X; local avgy = actor.Pos.Y - self.Pos.Y; local dist = math.sqrt(avgx ^ 2 + avgy ^ 2); if dist < curdist then curdist = dist; found = actor; end end --If no actor was found, try again next frame. Otherwise, continue. if found ~= nil then found.ToDelete = true; ActivityMan:GetActivity():ReportDeath(found.Team,-1); self.ctype = found.ClassName; self.cname = found.PresetName; self.cteam = found.Team; end end --Rain. if self.scriptTimer:IsPastRealMS(99999999999) == false then local drop = nil; drop = CreateAEmitter("Splashing Rain Drop"); drop.Pos.X = math.random(SceneMan.Scene.Width); drop.Vel.Y = 45; MovableMan:AddParticle(drop); if self.scriptTimer:IsPastRealMS(5000) then for i=1,math.random(5) do drop = CreateAEmitter("Splashing Rain Drop"); drop.Pos.X = math.random(SceneMan.Scene.Width); drop.Vel.Y = 45; MovableMan:AddParticle(drop); end end end --Small lightning. if self.scriptTimer:IsPastRealMS(34000) and self.scriptTimer:IsPastRealMS(60000) == false then if math.random() > 0.99 then local flash = CreateAEmitter("Lightning Flash " .. math.random(3) .. " With Sound"); flash.Pos = SceneMan:MovePointToGround(Vector(math.random(SceneMan.Scene.Width),0),0,0); MovableMan:AddParticle(flash); end end --Move the actor down. if MovableMan:IsActor(self.chosen) and self.scriptTimer:IsPastRealMS(203000) then if self.vincible == true then --Make the actor invincible. Store the parts in a list so we can set them back afterward. self.partslist = {}; for i=1,MovableMan:GetMOIDCount()-1 do if MovableMan:GetMOFromID(i).RootID == self.chosen.ID then self.partslist[#self.partslist + 1] = MovableMan:GetMOFromID(i); self.partslist[#self.partslist].GetsHitByMOs = false; end end --If we actually found any, then we say the actor is invincible. If not, try again next turn. if #self.partslist > 0 then self.vincible = false; end end --Used for measuring a few gradual things. local closeness = 1 - (self.chosen.Pos.Y / self.landspot.Y); --Move the actor gradually down until it reaches the desired position. self.chosen.Vel = Vector(0,0); self.chosen.Pos.X = self.Pos.X; self.chosen.AngularVel = 0; self.chosen.RotAngle = 0; local downam = closeness * 5; if downam < 1 then downam = 1; end self.chosen.Pos.Y = self.chosen.Pos.Y + downam; --Make the actor glow. self.chosen:FlashWhite(1); --Make the actor face forward. self.chosen:SetAimAngle(0); --Shut off the AI so it doesn't try to escape. self.chosen:SetControllerMode(Controller.CIM_DISABLED,-1); --Make it rain. if math.random() < closeness then local drop = nil; drop = CreateAEmitter("Splashing Rain Drop"); drop.Pos.X = math.random(SceneMan.Scene.Width); drop.Vel.Y = 45; MovableMan:AddParticle(drop); end --Fade out music gradually. local vol = closeness * 2; if vol > 1 then vol = 1; end AudioMan.MusicVolume = vol; --End this all if the chosen actor has arrived at its position. if self.chosen.Pos.Y > self.landspot.Y - 15 and self.chosen.Pos.Y < self.landspot.Y + 15 then self.ToDelete = true; self.chosen:SetControllerMode(Controller.CIM_AI,-1); --Make the actor vincible again. for i=1,#self.partslist do self.partslist[i].GetsHitByMOs = true; end --Stop music and reset settings. AudioMan:StopMusic(); AudioMan.MusicVolume = self.oldvol; AudioMan:ClearMusicQueue(); self.chosen.PinStrength = 0; end end end