package ControlPoint import UnitClass import Lightning import HeroClass import Fx import Colors import Setup import ClosureTimers import HashMap import Terrain import ObjEditingNatives import CrigBar import LinkedList public constant model = 'cptd' public constant modelMorphed = 'cpth' constant decoCystalGreenId = 'B00M' constant decoCystalRedId = 'B00L' constant decoLightGreenId = 'B00K' constant decoLightRedId = 'B00A' constant teamEverlivingLightning = FINGER_OF_DEATH constant teamWargrinLightning = "LEGR" constant real decoCrystalOusideScale = 0.4 constant real decoCrystalInsideScale = 0.8 constant int morphAbi = 'ctpm' constant real height = 400 constant real baseDmg = 2 constant real dmgPerLvl = 1 constant real percentualDmg = 0.2 constant real heroDmgFactor = 0.1 constant real unitDmgFactor = 0.01 constant real creepDmg = 0.75 constant real captureSpeedPoint = 0.0125 constant real captureSpeed = 0.01 constant real baseSHeal = 2.0 constant real heroSHealFactor = 0.1 constant real unitSHealFactor = 0.025 constant maxDistance = 990. constant captureDamage = 0.001 constant regenerationSpeed = 0.00005 function handle.getId() returns int return GetHandleId(this) public class CaptureData Unit owner lightning l1 = null lightning l2 = null real blitzPos = 0 boolean wantCapture = false Action onDeath = null Action captureCancel = null Fx fx = null construct(Unit u) owner = u ondestroy l1.destr() l2.destr() if onDeath != null destroy onDeath if fx != null destroy fx public class ControlPoint static HashMap captureData = new HashMap() static constant creationAction = Unit.onCreation((Unit u) -> captureData.put(u, new CaptureData(u))) static constant destructionAction = Unit.onDestroy((Unit u) -> destroy captureData.get(u)) timer rangeCheckTimer timer inRangeTimer vec3 pos3 vec2 pos2 unit clickDummy unit visualDummy group inRange = CreateGroup() int animationCounter = 0 CrigBar bar Team owner real hp = 0.05 //decovars destructable mainCrystal LinkedList outsideCrystals = new LinkedList() LinkedList glowMarkers = new LinkedList() construct(vec2 pos, Team owner) clickDummy = CreateUnit(Player(1), model, pos.x + 10, pos.y, 0) clickDummy.addAbility(morphAbi) clickDummy.setUserData(this castTo int) doAfter(1, () -> clickDummy.setVertexColor(colorA(0, 0, 0, 1))) clickDummy.addAbility('Arav') clickDummy.setFlyHeight(height + 40, 0) this.owner = owner pos2 = pos pos3 = pos.withZ(height) createDeco() rangeCheckTimer =getTimer()..setData(this castTo int)..startPeriodic(0.1, () -> GetExpiredTimer().getData() castTo thistype.inRangeCheck()) inRangeTimer = getTimer()..setData(this castTo int)..startPeriodic(0.03, () -> GetExpiredTimer().getData() castTo thistype.inRangeActions()) bar = new CrigBar(pos2, 250, 50) if(owner == Team.Everliving) bar.setBarColor(color(40, 255, 40)) bar.setBackground(color(255, 40, 40)) else bar.setBarColor(color(255, 40, 40)) bar.setBackground(color(40, 255, 40)) bar.setOffset(vec3(0, 70, height + 150)) // for int i = 1 to 360 step 2 // new Fx(pos2.polarOffset(i.toReal().asAngleDegrees(), getRadius(i.toReal().asAngleDegrees())), 0..asAngleDegrees(), "Abilities\\Weapons\\BoatMissile\\BoatMissile.mdl") private function getRadius(angle ang) returns real return maxDistance * Sin(60 * DEGTORAD) / (Sin((120 - (ang.degrees() + 30) % 60) * DEGTORAD)) private function isInRange(unit u) returns boolean return getRadius(pos2.angleTo(u.getPos())) >= u.getPos().distToVec(pos2) private function inRangeCheck() for unit u in ENUM_GROUP..enumUnitsInRange(pos2, maxDistance) if u.getUserData() != 0 and u != clickDummy and u.getAbilityLevel('dead') == 0 and not inRange.contains(u) and isInRange(u) enter(u.getUserData() castTo Unit) private function enter(Unit u) inRange.addUnit(u.u) let data = captureData.get(u) if u.team != owner string tempLightning if owner == Team.Everliving tempLightning = teamEverlivingLightning else tempLightning = teamWargrinLightning data.l1 = createLightning(tempLightning, u.getMiddle(), pos3) data.fx = new Fx(u.getMiddle(), 0..asAngleDegrees(), "Abilities\\Weapons\\WitchDoctorMissile\\WitchDoctorMissile.mdl") data.fx.setScale(2) data.fx.getDummy().setTimeScale(2) if data.wantCapture startCapture(u castTo Hero) data.onDeath = u.registerDeath((Units u) -> leave(u.target)) private function leave(Unit u) inRange.removeUnit(u.u) let data = captureData.get(u) if u.team != owner data.l1.destr() data.l1 = null destroy data.fx data.fx = null if data.l2 != null data.l2.destr() data.l2 = null data.blitzPos = 0 if data.wantCapture stopCapture(u castTo Hero) if data.captureCancel != null destroy data.captureCancel data.captureCancel = null destroy data.onDeath data.onDeath = null private function inRangeActions() hp += regenerationSpeed if hp > 1 hp = 1 if hp <=0 changeOwner() bar.setPercentage(1 - hp) for unit temp in inRange Unit u = temp.getUserData() castTo Unit if temp.getPos().distToVec(pos2) < getRadius(temp.getPos().angleTo(pos2)) let data = captureData.get(u) if owner == u.team u.healSystem(1) else if data.l2 == null data.l1.setPos(u.getMiddle(), pos3) data.fx.setXY(temp.getPos()) u.damageSystem(1) else captures(u castTo Hero, data) else leave(u) private function captures(Hero h, CaptureData data) if data.wantCapture vec3 pos = h.getCaptureAttackPoint(pos2) if data.blitzPos < 1 data.blitzPos += captureSpeed data.fx.setXYZ(getBlitzPos(pos, data.blitzPos), true) else hp -= captureDamage data.l1.setPos(data.fx.getPos3d(), pos3) data.l2.setPos(pos, data.fx.getPos3d()) else vec3 pos = h.getMiddle() if data.blitzPos > 0 data.blitzPos -= captureSpeed data.fx.setXYZ(getBlitzPos(pos, data.blitzPos), true) data.l1.setPos(data.fx.getPos3d(), pos3) data.l2.setPos(pos, data.fx.getPos3d()) else data.l2.destr() data.l2 = null data.fx.setXYZ(pos, true) private function getBlitzPos(vec3 pos, real progress) returns vec3 vec3 dif = pos3 - pos return pos + dif * progress function wantCapture(Hero h) returns boolean var data = captureData.get(h) if not data.wantCapture and h.team != owner data.wantCapture = true if inRange.contains(h.u) startCapture(h) data.captureCancel = h.registerCaptureCancel((ControlPoint cp) -> begin if cp != this data.wantCapture = false if inRange.contains(h.u) stopCapture(h) destroy data.captureCancel data.captureCancel = null end) return not inRange.contains(h.u) private function startCapture(Hero h) h.enableAutoAttack(false) IssueImmediateOrder(h.u, "stop") h.u.setFacing(h.u.getPos().angleTo(pos2)) h.playCaptureAnimation() var data = captureData.get(h) if data.l2 == null string tempLightning if owner != Team.Everliving tempLightning = teamEverlivingLightning else tempLightning = teamWargrinLightning data.l2 = createLightning(tempLightning, h.getMiddle(), data.fx.getPos3d()) private function stopCapture(Hero h) h.enableAutoAttack(true) h.stopAnimation() private function playCapturedAnimation() getTimer()..setData(this castTo int).startPeriodic(0.01, () -> GetExpiredTimer().getData() castTo thistype.playCaptureAnimationCallback()) private function playCaptureAnimationCallback() Fx fx = new Fx(pos2.polarOffset(animationCounter.toReal().asAngleDegrees(), getRadius(animationCounter.toReal().asAngleDegrees())), 0..asAngleDegrees(), "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl") doAfter(1, () -> destroy fx) animationCounter++ private function changeOwner() print("ownerchange") real z = getTerrainZ(pos2) for unit u from inRange Unit ug = u.getUserData() castTo Unit leave(ug) captureData.get(ug).wantCapture = false if owner == Team.Everliving owner = Team.Wargrin else owner = Team.Everliving inRangeTimer.release() rangeCheckTimer.release() int newCrystalId string lightningId string effectPath string mainEffectPath int newDecoId var tempOutsideCrystals = outsideCrystals outsideCrystals = new LinkedList() var tempGlowMarkers = glowMarkers glowMarkers = new LinkedList() if owner == Team.Everliving newCrystalId = decoCystalRedId lightningId = teamEverlivingLightning newDecoId = decoLightRedId effectPath = "Abilities\\Spells\\Human\\MarkOfChaos\\MarkOfChaosDone.mdl" mainEffectPath = "CaptureEffect_Coil_Red.mdl" else newCrystalId = decoCystalGreenId lightningId = teamWargrinLightning newDecoId = decoLightGreenId effectPath = "CaptureEffect_Green.mdl" mainEffectPath = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl" Fx mainCrystalFx = new Fx(pos2.withZ(height - 135), 0..asAngleDegrees(), mainEffectPath) mainCrystalFx.setScale(3.2) doAfter(1, () -> begin destroy mainCrystalFx for destructable des in tempOutsideCrystals vec3 desPos = vec3(des.getX(), des.getY(), 110) lightning ls = createLightning(lightningId, desPos, pos3) Fx sideCrystalFx = new Fx(desPos, 0..asAngleDegrees(), effectPath) doAfter(0.5, () -> begin RemoveDestructable(des) outsideCrystals.add(CreateDestructableZ(newCrystalId, desPos.x, desPos.y, z + 100, 0, decoCrystalOusideScale, 0)) real ang = 0 for destructable marker in tempGlowMarkers vec3 markerPos = vec3(marker.getX(), marker.getY(), z) RemoveDestructable(marker) glowMarkers.add(CreateDestructableZ(newDecoId, markerPos.x, markerPos.y, z, ang + 270, 7.80, 0)) ang += 60 end) doAfter(1, () -> begin ls.destr() destroy sideCrystalFx end) doAfter(1, () -> begin rangeCheckTimer =getTimer()..setData(this castTo int)..startPeriodic(0.1, () -> GetExpiredTimer().getData() castTo thistype.inRangeCheck()) inRangeTimer = getTimer()..setData(this castTo int)..startPeriodic(0.03, () -> GetExpiredTimer().getData() castTo thistype.inRangeActions()) hp = 0.5 if(owner == Team.Everliving) bar.setBarColor(color(40, 255, 40)) bar.setBackground(color(255, 40, 40)) else bar.setBarColor(color(255, 40, 40)) bar.setBackground(color(40, 255, 40)) end) end) doAfter(0.5, () -> begin RemoveDestructable(mainCrystal) mainCrystal = CreateDestructableZ(newCrystalId, pos2.x - 10, pos2.y, z + height - 35, 0, decoCrystalInsideScale, 0) end) private function createDeco() real z = getTerrainZ(pos2) if owner == Team.Everliving mainCrystal = CreateDestructableZ(decoCystalRedId, pos2.x - 10, pos2.y, z + height - 35, 0, decoCrystalInsideScale, 0) for int i = 30 to 360 step 60 vec2 tempPos = pos2.polarOffset(i.toReal().asAngleDegrees(), getRadius(i.toReal().asAngleDegrees()) - 160) outsideCrystals.add(CreateDestructableZ(decoCystalRedId, tempPos.x, tempPos.y, z + 100,i.toReal(), decoCrystalOusideScale, 0)) for int i = 0 to 300 step 60 vec2 tempPos = pos2.polarOffset(i.toReal().asAngleDegrees(), getRadius(i.toReal().asAngleDegrees())) glowMarkers.add(CreateDestructableZ(decoLightRedId, tempPos.x, tempPos.y, z, i.toReal() + 270, 7.80, 0)) else mainCrystal = CreateDestructableZ(decoCystalGreenId, pos2.x - 10, pos2.y, z + height - 35, 0, decoCrystalInsideScale, 0) for int i = 30 to 360 step 60 vec2 tempPos = pos2.polarOffset(i.toReal().asAngleDegrees(), getRadius(i.toReal().asAngleDegrees()) - 160) outsideCrystals.add(CreateDestructableZ(decoCystalGreenId, tempPos.x, tempPos.y, z + 100,i.toReal(), decoCrystalOusideScale, 0)) for int i = 0 to 300 step 60 vec2 tempPos = pos2.polarOffset(i.toReal().asAngleDegrees(), getRadius(i.toReal().asAngleDegrees())) glowMarkers.add(CreateDestructableZ(decoLightGreenId, tempPos.x, tempPos.y, z, i.toReal() + 270, 7.80, 0)) @compiletime function create_w3a_ctpm() let u = createObjectDefinition("w3a", 'ctpm', 'Sca6') u.setLvlDataString("Cha1", 1, 0, "cpth") u.setLvlDataString("areq", 0, 0, "") @compiletime function create_w3u_cpth() let u = createObjectDefinition("w3u", 'cpth', 'hpea') u.setInt("uhpm", 500000) u.setString("unam", "Controlpoint Unit (Dummy)") u.setInt("umvs", 0) u.setString("ushu", "") u.setString("umdl", "Abilities\\Weapons\\BoatMissile\\BoatMissile.mdl") u.setUnreal("umvf", 150.0) u.setUnreal("umvh", 150.0) u.setString("uabi", "Avul") u.setString("upgr", "") u.setString("ubui", "") u.setString("umvt", "hover") u.setReal("usca", 6.0) u.setInt("uaen", 0) @compiletime function create_w3u_cptd() let u = createObjectDefinition("w3u", 'cptd', 'hpea') u.setInt("uhpm", 500000) u.setString("unam", "Controlpoint Unit (Dummy)") u.setInt("umvs", 0) u.setString("ushu", "") u.setString("umdl", "Abilities\\Weapons\\BoatMissile\\BoatMissile.mdl") u.setUnreal("umvf", 150.0) u.setUnreal("umvh", 150.0) u.setString("uabi", "Avul,Aloc") u.setString("upgr", "") u.setString("ubui", "") u.setString("umvt", "hover") u.setReal("usca", 6.0) u.setInt("uaen", 0)