package SetupObject import public Entity import public TerrainUtils import public ConfigValue import public Json import public BuilderConstants import public initlater RegionData import public ClosureForGroups import ClosureEvents_config /** Objects which are unclickable for escapers, but clickable for builders. They have a dummy unit that is invisible to escapers but clickable by builder, and the actor unit is locusted so it cannot be clicked by escaper, but seen. */ let fixPos = CreateTimer() public abstract class SetupObject extends UnitEntity private real time = GetRandomReal(30,45) boolean enabled = true unit setup construct(unit actor, unit setup, real radius) super(actor) this.setup = setup this.radius = radius fire[actor.getIndex()] = true actor..setEntity(this)..addAbility(LOCUST_ID)..removeAbility(REMOVE_OBJECT_ID)..setPathing(true) setup..setEntity(this)..setXY(actor.getPos()) ..addAbility(GHOST_INVIS_ID)..addAbility(REMOVE_OBJECT_ID)..addAbility(HEIGHT_ENABLER)..removeAbility(HEIGHT_ENABLER) this.setCurrentRegion() EventListener.add(setup, EVENT_PLAYER_UNIT_ISSUED_ORDER, () -> onOrderEvent()) EventListener.add(setup, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, () -> onOrderEvent()) EventListener.add(setup, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, () -> onOrderEvent()) function setEnabled(boolean flag) if flag and not enabled enabled = true setup..removeAbility(TURN_ON_ID)..addAbility(TURN_OFF_ID) else if enabled enabled = false setup..removeAbility(TURN_OFF_ID)..addAbility(TURN_ON_ID) override function setPos(vec3 pos) this.pos = pos setup.setPosFly(pos) actor.setPosFly(pos) override function setXY(vec3 pos) this.pos = pos actor.setXYZ(pos) setup.setXYZ(pos) function setFacing(angle angl) actor.setFacing(angl) setup.setFacing(angl) override function update() super.update() time-=ANIMATION_PERIOD checkReposition() override function slowUpdate() time-=1.0 checkReposition() function checkReposition() if time < 0 setup.setXY(getPos()) setup.setFacing(actor.getFacingAngle()) time = GetRandomReal(30,45) ondestroy fire[actor.getIndex()] = false unregisterEventsForUnit(setup) setup.setEntity(null) setup.remove() setup = null function onOrderEvent() let order = GetIssuedOrderId() let targetPos = EventData.getOrderPos() let u = GetOrderTargetUnit() let orderS = OrderId2String(order) if orderS == "smart" or orderS == "move" or orderS == "attack" or orderS == "patrol" or orderS == "holdposition" or orderS == "stop" Log.trace("actor mimick move order") if orderS == "smart" and u == null actor.issuePointOrder("move", targetPos+getOffset()) else if u != null actor.issueTargetOrderById(order, u) else if targetPos.x != 0. actor.issuePointOrderById(order, targetPos) else actor.issueImmediateOrderById(order) else if not orderS == "waterelemental" and not orderS == "roar" and not order == 851974 actor.issueImmediateOrder("stop") Log.trace("stopping actor") pos = setup.getPos3Zero() actor..setXY(pos) ..setFacing(setup.getFacingAngle()) ..setTurnSpeed(GetUnitTurnSpeed(setup)) public abstract class StaticSetupObject extends UnitEntity unit setup trigger inRangeTrig = null // Trigger for inRange detection construct(unit u, unit setup, real radius, code c) super(u) deactivate() actor.addAbility(LOCUST_ID) setup..addAbility(GHOST_INVIS_ID)..addAbility(REMOVE_OBJECT_ID) ..setVertexColor(colorA(255, 255, 255, 155)) this.setup = setup if radius > 0. // a few Objects like Spinner dont have inRange Events, we dont want to create unused triggers inRangeTrig = CreateTrigger() ..registerUnitInRangeSource(setup, radius) ..addAction(c) setup.setEntity(this) override function update() function setNewSetup(unit u) if u == null or not u.isAlive() or u.getEntity() != null error("invalid actor replacement") setup.setEntity(null) setup.remove() setup = u setup.setEntity(this) ondestroy unregisterEventsForUnit(setup) setup.clearRegister() setup.setEntity(null) setup.remove() setup = null if inRangeTrig != null inRangeTrig.destr() inRangeTrig = null var count = -1 let offsets = [vec2(0.049, 0.001), vec2(0.048, 0.002), vec2(0.047, 0.003), vec2(0.046, 0.004), vec2(0.045, 0.005), vec2(0.044, 0.006), vec2(0.043, 0.007), vec2(0.041, 0.008), vec2(0.040, 0.009), vec2(0.039, 0.008), vec2(0.038, 0.007), vec2(0.037, 0.006), vec2(0.036, 0.005), vec2(0.035, 0.004), vec2(0.034, 0.003), vec2(0.033, 0.002), vec2(0.032, 0.001), vec2(0.031, 0.002), vec2(0.030, 0.003), vec2(0.029, 0.004), vec2(0.028, 0.005), vec2(0.027, 0.006), vec2(0.026, 0.007), vec2(0.025, 0.008), vec2(0.024, 0.009), vec2(0.023, 0.008), vec2(0.022, 0.007), vec2(0.021, 0.006), vec2(0.020, 0.005), vec2(0.019, 0.004), vec2(-0.049, 0.003), vec2(-0.048, 0.002), vec2(-0.047, 0.001), vec2(-0.046, 0.002), vec2(-0.045, 0.003), vec2(-0.044, 0.004), vec2(-0.043, 0.005), vec2(-0.041, 0.006), vec2(-0.040, 0.007), vec2(-0.039, 0.008), vec2(-0.038, 0.009), vec2(-0.037, 0.008), vec2(-0.036, 0.007), vec2(-0.035, 0.006), vec2(-0.034, 0.005), vec2(-0.033, 0.004), vec2(-0.032, 0.003), vec2(-0.031, 0.002), vec2(-0.030, 0.001), vec2(-0.029, 0.002), vec2(-0.028, 0.003), vec2(-0.027, 0.004), vec2(-0.026, 0.005), vec2(-0.025, 0.006), vec2(-0.024, 0.007), vec2(-0.023, 0.008), vec2(-0.022, 0.009), vec2(-0.021, 0.000), vec2(-0.020, 0.009), vec2(-0.019, 0.008)] function getOffset() returns vec2 count++ if count > 50 count = -1 return offsets[count]