/** If you import this package in any of your packages, each order any unit makes will be recorded and up to ORDERS_TO_HOLD will be saved. You can access these old orders and reissue them using .getLastOrder() */ package LastOrder import RegisterEvents import UnitIndexer /** How many past orders to hold. Should be at least 2 */ @configurable constant ORDERS_TO_HOLD = 3 /** Clears all recorded orders for this unit */ public function unit.clearLastOrders() let index = this.getIndex() if lastOrder[index] != null destroy lastOrder[index] lastOrder[index] = null /** Returns the lasz recorded order for this unit. To access further back orders, use .prev */ public function unit.getLastOrder() returns Order return lastOrder[this.getIndex()] public enum OrderType TARGET POINT IMMEDIATE Order array lastOrder public class Order Order prev = null OrderType orderType unit orderedUnit = null var orderId = -1 widget target vec2 targetPosition var finished = false construct(unit ordered, int orderId, OrderType ordtype, widget target, vec2 targetPos) this.orderedUnit = ordered this.orderId = orderId this.orderType = ordtype this.target = target this.targetPosition = targetPos if ordered != null let index = ordered.getIndex() if lastOrder[index] != null if lastOrder[index].orderedUnit == orderedUnit prev = lastOrder[index] else destroy lastOrder[index] var i = 0 var e = this while e.prev != null i++ if i > ORDERS_TO_HOLD let tmp = e.prev destroy tmp e.prev = null break e = e.prev lastOrder[index] = this ondestroy if prev != null destroy prev prev = null /** Reissues this order on the unit that originally received the order. If you want the reissued order to be recorded as well, in a response to another order, i.e. chained, you need to wrap it inside using a nulltimer: let ordr = caster.getLastOrder().prev nullTimer() -> ordr.issue() */ function issue() returns boolean if orderedUnit.getTypeId() != 0 and not orderedUnit.isType(UNIT_TYPE_DEAD) and not finished switch orderType case TARGET return orderedUnit.issueTargetOrderById(orderId, target) case POINT if orderId == 851971 // This adjusts for a bug in the point order's boolean return when issuing a smart order orderedUnit.issuePointOrderById(orderId, targetPosition) return true else return orderedUnit.issuePointOrderById(orderId, targetPosition) case IMMEDIATE return orderedUnit.issueImmediateOrderById(orderId) return false /** Use this to copy this order to apply it to another unit. The copy must be destroyed manually. */ function copy() returns Order return new Order(null, orderId, orderType, target, targetPosition) function badOrderList(int id) returns boolean return (id==852055 or id==852056 or id==852064 or id==852065 or id==852067 or id==852068 or id==852076 or id==852077 or id==852090 or id==852091 or id==852100 or id==852102 or id==852103 or id==852107 or id==852108 or id==852129 or id==852130 or id==852133 or id==852134 or id==852136 or id==852137 or id==852150 or id==852151 or id==852174 or id==852158 or id==852159 or id==852162 or id==852163 or id==852174 or id==852175 or id==852177 or id==852178 or id==852191 or id==852192 or id==852198 or id==852199 or id==852203 or id==852204 or id==852212 or id==852213 or id==852244 or id==852245 or id==852249 or id==852250 or id==852255 or id==852256 or id==852458 or id==852459 or id==852478 or id==852479 or id==852484 or id==852485 or id==852515 or id==852516 or id==852522 or id==852523 or id==852540 or id==852541 or id==852543 or id==852544 or id==852546 or id==852547 or id==852549 or id==852550 or id==852552 or id==852553 or id==852562 or id==852563 or id==852571 or id==852578 or id==852579 or id==852589 or id==852590 or id==852602 or id==852603 or id==852671 or id==852672) function unit.orderFilter(int id) returns boolean return (id == 851971 or id == 851986 or id == 851983 or id == 851984 or id == 851990 or id == 851993 or (id >= 852055 and id <= 852762)) and not badOrderList(id) public function unit.abortOrder() returns boolean if this.isPaused() return false else this..unpause()..issueImmediateOrder("stop")..pause() return true function conditions() returns boolean return GetTriggerUnit().orderFilter(GetIssuedOrderId()) function actions() if conditions() let u = GetTriggerUnit() let t = GetOrderTarget() let oid = GetIssuedOrderId() Log.trace("ordered: <" + OrderId2StringBJ(oid) + ">") if GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER new Order(u, oid, OrderType.TARGET, t, EventData.getOrderTargetPos()) else if GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER new Order(u, oid, OrderType.POINT, null, EventData.getOrderPos()) else if GetTriggerEventId() == EVENT_PLAYER_UNIT_ISSUED_ORDER new Order(u, oid, OrderType.IMMEDIATE, null, u.getPos()) function spellActions() let index = GetTriggerUnit().getIndex() if lastOrder[index] != null // Only do this if the last order actually exists lastOrder[index].finished = true init registerPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null, function actions) registerPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, null, function actions) registerPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER, null, function actions) registerPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, null, function spellActions) onUnitDeindex() -> getIndexingUnit().clearLastOrders()