scope PedestalReceive initializer init import Units import Game import TerrainData import RegisterPlayerUnitEvent import SoundControl import DummyUnitStack constant string DUMMY_MODEL = "Abilities\\Weapons\\FaerieDragonMissile\\FaerieDragonMissile.mdl" constant string EFFECT_MODEL = "Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl" constant string RUNE_SECURED = "rune-secured.mp3" constant integer PEDESTAL_ID = 'h003' constant integer SPAWN_COUNT = 20 constant real ENUM_EPSILON = 32. constant vec3 TARGET_PILLAR_LEFT = vec3(-1630., 3798., 100.) constant vec3 TARGET_PILLAR_RIGHT = vec3(-1470., 3644., 100.) // matches gameplay constant - "Inventory - Drop Item Range" constant real ITEM_DROP_OFFS = 100. constant real ITEM_SPAWN_HEIGHT = 40. constant real SPAWN_PERIOD = 1. / 10. constant real INITIAL_PITCH = 13. * PI / 32. constant real INITIAL_VELOCITY = 500. constant real ACCELERATION = 80. constant real CLOCK_PERIOD = 1. / 30. constant real AIR_FRICTION = CLOCK_PERIOD * 7. / 5. struct Effect vec3 velocity vec3 target unit dummy effect attached end timer time = CreateTimer() timer time2 = CreateTimer() group grp = CreateGroup() rect rctEpsilon item fakeRune = CreateItem('I000', TerrainData.SAFE_X, TerrainData.SAFE_Y) integer spawnCount integer effectIndex = -1 Effect array fxDb function fxSpawn3 takes nothing returns nothing integer index = 0 Effect iter vec3 diff real dX real dY real dH loop exitwhen index > effectIndex iter = fxDb[index] dX = iter.dummy.getX() dY = iter.dummy.getY() dH = iter.dummy.getFlyHeight() diff = iter.target - vec3(dX, dY, dH) iter.velocity += ACCELERATION * CLOCK_PERIOD * diff.norm() iter.velocity *= (1. - AIR_FRICTION) iter.dummy.setX(dX + iter.velocity.x) iter.dummy.setY(dY + iter.velocity.y) iter.dummy.setFlyHeight(dH + iter.velocity.z, 0.) if Game.roundEnabled or vec3(dX + iter.velocity.x, dY + iter.velocity.y, dH + iter.velocity.z).distToVec(iter.target) < 2. * iter.velocity.length() then iter.attached.destr() iter.dummy.setX(iter.target.x) iter.dummy.setY(iter.target.y) iter.dummy.setFlyHeight(iter.target.z, 0.) AddSpecialEffectTarget(EFFECT_MODEL, iter.dummy, "origin").destr() DummyUnitStack.delayedRelease(iter.dummy, 1.) destroy iter fxDb[index] = fxDb[effectIndex] effectIndex-- index-- if effectIndex == -1 then time2.pause() end end index++ end end function fxSpawn2 takes nothing returns nothing Effect fx real randTarget = GetRandomReal(0., 1.) real randAng = GetRandomReal(0., 2. * PI) if spawnCount > 0 and not Game.roundEnabled then fx = new Effect() fx.velocity = vec3(INITIAL_VELOCITY * CLOCK_PERIOD * Cos(INITIAL_PITCH) * Cos(randAng), INITIAL_VELOCITY * CLOCK_PERIOD * Cos(INITIAL_PITCH) * Sin(randAng), INITIAL_VELOCITY * CLOCK_PERIOD * Sin(INITIAL_PITCH)) fx.dummy = DummyUnitStack.get() fx.attached = AddSpecialEffectTarget(DUMMY_MODEL, fx.dummy, "origin") fx.dummy.setFlyHeight(ITEM_SPAWN_HEIGHT, 0.) fx.dummy.setPos(GetItemX(fakeRune), GetItemY(fakeRune)) if randTarget < .5 then fx.target = TARGET_PILLAR_LEFT else fx.target = TARGET_PILLAR_RIGHT end effectIndex++ fxDb[effectIndex] = fx if effectIndex == 0 then time2.startPeriodic(CLOCK_PERIOD, function fxSpawn3) end spawnCount-- else time.pause() fakeRune.setPos(TerrainData.SAFE_X, TerrainData.SAFE_Y) end end function fxSpawn takes unit u, real facing returns nothing fakeRune.setPos(GetUnitX(u) + ITEM_DROP_OFFS * Cos(facing), GetUnitY(u) + ITEM_DROP_OFFS * Sin(facing)) spawnCount = SPAWN_COUNT TimerStart(time, SPAWN_PERIOD, true, function fxSpawn2) end function act takes nothing returns nothing unit iter // search group for artifact GroupEnumUnitsInRect(grp, rctEpsilon, null) loop iter = FirstOfGroup(grp) exitwhen iter == null if (UnitHasItem(iter, Units.artifact) or UnitHasItem(iter, Units.artifact2)) and Game.roundEnabled then SoundControl.play(RUNE_SECURED, 1., 127) FogEnable(false) PanCameraToTimed(GetUnitX(iter), GetUnitY(iter), 0.) SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, 1024., 0.) fxSpawn(iter, iter.getFacing()) Game.hunterWin() SetItemPosition(Units.artifact, TerrainData.SAFE_X, TerrainData.SAFE_Y) SetItemPosition(Units.artifact2, TerrainData.SAFE_X, TerrainData.SAFE_Y) exitwhen true end GroupRemoveUnit(grp, iter) end end function init takes nothing returns nothing trigger trig = CreateTrigger() rect rct = Rect(TerrainData.HALL_MIN_X, TerrainData.HALL_MIN_Y, TerrainData.HALL_MAX_X, TerrainData.HALL_MAX_Y) region reg = CreateRegion() RegionAddRect(reg, rct) rctEpsilon = Rect(TerrainData.HALL_MIN_X - ENUM_EPSILON, TerrainData.HALL_MIN_Y - ENUM_EPSILON, TerrainData.HALL_MAX_X + ENUM_EPSILON, TerrainData.HALL_MAX_Y + ENUM_EPSILON) registerPlayerUnitEvent(EVENT_PLAYER_UNIT_PICKUP_ITEM, function act) TriggerRegisterEnterRegion(trig, reg, null) TriggerAddAction(trig, function act) SoundControl.preload(RUNE_SECURED) RemoveRect(rct) end endscope