package CongaLineHead import SetupObject import Spinner import CongaObjects import Interpolation public enum CongaMode STRICT LOOSE PENDULUM class CongaSegment CongaSegment next = null CongaSegment prev = null SetupObject target CongaLineHead head real mass = 1 angle phi = angle(0) real dPhi = 0 real angularMomentum = 0 construct(CongaLineHead head, SetupObject target) this.target = target this.head = head target.setup.removeAbility(REMOVE_OBJECT_ID) phi = head.getPos().angleTo2d(target.getPos()) function calcPos() if head.cmode == CongaMode.STRICT if prev == null target.setNewPosA(calculateSegmentPos(head.pos.toVec2(), target.pos.toVec2(), 75.), target.pos.angleTo2d(head.pos)) else target.setNewPosA(calculateSegmentPos(prev.target.pos.toVec2(), target.pos.toVec2(), head.segLength), target.pos.angleTo2d(prev.target.pos)) else if head.cmode == CongaMode.LOOSE if prev == null if target.pos.distanceTo2dSq(head.getPos().toVec2()) > 32*32 target.setNewPosA(target.pos.toVec2().lerp(head.pos.toVec2(), head.segLength * 0.001), target.pos.angleTo2d(head.pos)) else if target.pos.distanceTo2dSq(prev.target.pos.toVec2()) > 24*24 target.setNewPosA(target.pos.toVec2().lerp(prev.target.pos.toVec2(), head.segLength * 0.001), target.pos.angleTo2d(prev.target.pos)) ondestroy if next != null next.prev = prev if prev != null prev.next = next if head.firstSegment == this head.firstSegment = next if not target.done and target.actor != null target.setup.addAbility(REMOVE_OBJECT_ID) public class CongaLineHead extends SetupObject CongaSegment firstSegment = null CongaMode cmode = CongaMode.LOOSE real segLength = 75. construct(vec2 pos, player owner) super(createUnit(owner, CONGA_LINE_HEAD_ID, pos, angle(0)), createUnit(owner, CONGA_LINE_HEAD_ID, pos, angle(0)), 0.) EventListener.add(setup, EVENT_PLAYER_UNIT_SPELL_CAST, () -> onCast()) sleeps = false setup.addAbility(CONGA_CONFIG_ID) override function update() super.update() var segment = firstSegment while segment != null segment.calcPos() segment = segment.next function addSegment(SetupObject e) boolean isNew = true var segment = firstSegment while segment != null if segment.target == e isNew = false break segment = segment.next if isNew if firstSegment == null firstSegment = new CongaSegment(this, e) else segment = firstSegment while segment.next != null segment = segment.next segment.next = new CongaSegment(this, e) segment.next.prev = segment segment.next.phi = e.getPos().angleTo2d(pos.toVec2()) else destroy segment function onCast() let id = GetSpellAbilityId() let t = GetSpellTargetUnit() switch id case ADD_ID let ed = t.getEntity() if ed.owner == owner and ed instanceof SetupObject addSegment(ed castTo SetupObject) case INC_ID if segLength < 500. segLength += 25 createFText(pos, vec2(0,0.05), "Segment Length: "+ R2SW(segLength,1,2), 10, 2., colorA(255,255,255,0), owner) else createFText(pos, vec2(0,0.05), "Maximum Speed", 10, 2., colorA(255,255,255,0), owner) case DEC_ID if segLength > 25 segLength -= 25 createFText(pos, vec2(0,0.05), "Segment Length: "+ R2SW(segLength,1,2), 10, 2., colorA(255,255,255,0), owner) else createFText(pos, vec2(0,0.05), "Minimum Speed", 10, 2., colorA(255,255,255,0), owner) case CONGA_STRICT_ID cmode = CongaMode.STRICT case CONGA_LOOSE_ID cmode = CongaMode.LOOSE override function serialize() returns Json let json = super.serialize() json ..addProperty(new Property(KEY_TYPE, CONGA_INDEX.toString())) return json override function setEnabled(boolean b) ondestroy var l = firstSegment while l != null let tmp = l l = l.next destroy tmp function UnitEntity.setNewPosA(vec2 tpos, angle angl) if this instanceof SetupObject (this castTo SetupObject).setXY(tpos.toVec3()) (this castTo SetupObject).setFacing(angl) else if this instanceof Spinner (this castTo Spinner).setXY(tpos.toVec3()) (this castTo Spinner).actor.setFacing(angl) function calculateSegmentPos(vec2 pos1, vec2 pos2, angle a, real segLength) returns vec2 let angl = pos2.angleTo(pos1) + a return vec2(pos1.x - Cos(angl.radians()) * segLength, pos1.y - Sin(angl.radians()) * segLength) function calculateSegmentPos(vec2 pos1, vec2 pos2, real segLength) returns vec2 let angl = pos2.angleTo(pos1) return vec2(pos1.x - Cos(angl.radians()) * segLength, pos1.y - Sin(angl.radians()) * segLength)