From 47dad828fc36aeb607e8f2ae91b631e0ce611d38 Mon Sep 17 00:00:00 2001 From: Frotty Date: Tue, 17 Feb 2026 10:51:34 +0100 Subject: [PATCH 01/10] Guard for getEnterLeaveUnit --- wurst/event/OnUnitEnterLeave.wurst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wurst/event/OnUnitEnterLeave.wurst b/wurst/event/OnUnitEnterLeave.wurst index 4039eb3e3..1f564586c 100644 --- a/wurst/event/OnUnitEnterLeave.wurst +++ b/wurst/event/OnUnitEnterLeave.wurst @@ -37,6 +37,8 @@ function popUnit() /** Returns the unit that caused the enter/leave event to happen */ public function getEnterLeaveUnit() returns unit + if tempUnitsCount <= 0 + return null return tempUnits[tempUnitsCount - 1] /** Adds a callback that is run when a unit enters the map */ From a0ff0ba7d7a75a49adc32711c5dc47ffadc89585 Mon Sep 17 00:00:00 2001 From: Frotty Date: Tue, 17 Feb 2026 10:51:49 +0100 Subject: [PATCH 02/10] Use new native for group iterator --- wurst/_handles/Group.wurst | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/wurst/_handles/Group.wurst b/wurst/_handles/Group.wurst index 1e4807ce5..901ee2a97 100755 --- a/wurst/_handles/Group.wurst +++ b/wurst/_handles/Group.wurst @@ -111,14 +111,32 @@ public function group.get(int index) returns unit return BlzGroupUnitAt(this, index) /* Group iterator */ +class GroupIterator + private group g + private int i = 0 + private int n = 0 -group iterGroup + construct(group source) + g = CreateGroup() + g.add(source) + n = g.size() + + function hasNext() returns bool + return i < n + + function next() returns unit + let u = g.get(i) + i += 1 + return u + + function close() + g.clear() + g.destr() + destroy this /** Creates a new iterator for this group. */ -public function group.iterator() returns group - iterGroup = CreateGroup() - iterGroup.add(this) - return iterGroup +public function group.iterator() returns GroupIterator + return new GroupIterator(this) /** Returns whether the iterator has the next item */ public function group.hasNext() returns bool From 6cd38af1cc074f292ec6494be4ec2b14bdaa0735 Mon Sep 17 00:00:00 2001 From: Frotty Date: Tue, 17 Feb 2026 10:53:02 +0100 Subject: [PATCH 03/10] Update Group.wurst --- wurst/_handles/Group.wurst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wurst/_handles/Group.wurst b/wurst/_handles/Group.wurst index 901ee2a97..521d1652c 100755 --- a/wurst/_handles/Group.wurst +++ b/wurst/_handles/Group.wurst @@ -130,9 +130,11 @@ class GroupIterator return u function close() + destroy this + + ondestroy g.clear() g.destr() - destroy this /** Creates a new iterator for this group. */ public function group.iterator() returns GroupIterator From b191c71626ac6dd79c921e57ef833d63f4fb277c Mon Sep 17 00:00:00 2001 From: Frotty Date: Tue, 17 Feb 2026 11:06:58 +0100 Subject: [PATCH 04/10] Delete DamageDetection.wurst --- wurst/event/DamageDetection.wurst | 71 ------------------------------- 1 file changed, 71 deletions(-) delete mode 100644 wurst/event/DamageDetection.wurst diff --git a/wurst/event/DamageDetection.wurst b/wurst/event/DamageDetection.wurst deleted file mode 100644 index 91e1d32aa..000000000 --- a/wurst/event/DamageDetection.wurst +++ /dev/null @@ -1,71 +0,0 @@ -package DamageDetection -import OnUnitEnterLeave - -/** - Use `addOnDamageFunc` to add a listener to any damage event that happens on the map. - Example: - - init - addOnDamageFunc() -> - print("Damage Event with dmg: " + GetEventDamage().toString()) -*/ - -@configurable constant SWAP_TIMEOUT = 600. - -boolexpr array func -int funcNext = 0 -trigger current = null -trigger toDestroy = null - -constant filter = Filter(() -> addUnit(GetFilterUnit())) - -function addUnit(unit u) - current.registerUnitEvent(u, EVENT_UNIT_DAMAGED) - -/** Add a Action to the damage Event. */ -public function addOnDamageFunc(code c) - let cf = Condition(c) - current.addCondition(cf) - func[funcNext] = cf - funcNext++ - -/** Add a Condition(Action) to the damage Event. */ -public function addOnDamageFunc(boolexpr cf) - current.addCondition(cf) - func[funcNext] = cf - funcNext++ - -/** Disables the damage events */ -public function disableDamageDetect() - DisableTrigger(current) - -/** Enables the damage events */ -public function enableDamageDetect() - EnableTrigger(current) - -/** Periodic Cleanup-Function */ -function swap() - let isEnabled = IsTriggerEnabled(current) - - current.disable() - if toDestroy != null - toDestroy.destr() - - toDestroy = current - current = CreateTrigger() - - if not isEnabled - current.disable() - - ENUM_GROUP.enumUnitsAll(filter) - - for i = 0 to funcNext - 1 - current.addCondition(func[i]) - -init - current = CreateTrigger() - for i = 0 to funcNext - 1 - current.addCondition(func[i]) - - onEnter(() -> addUnit(getEnterLeaveUnit())) - CreateTimer().startPeriodic(SWAP_TIMEOUT, function swap) From d2504789ea574aba6b7728fe662c06b467948594 Mon Sep 17 00:00:00 2001 From: Frotty Date: Tue, 17 Feb 2026 11:16:24 +0100 Subject: [PATCH 05/10] Update ClosureForGroups.wurst --- wurst/closures/ClosureForGroups.wurst | 156 +++++++++++++++++++++----- 1 file changed, 129 insertions(+), 27 deletions(-) diff --git a/wurst/closures/ClosureForGroups.wurst b/wurst/closures/ClosureForGroups.wurst index 4dee21321..49dc42c39 100644 --- a/wurst/closures/ClosureForGroups.wurst +++ b/wurst/closures/ClosureForGroups.wurst @@ -3,34 +3,75 @@ package ClosureForGroups public interface ForGroupCallback function callback(unit u) +/** Return true to continue iteration, false to stop. */ +public interface ForGroupCallbackUntil + function callback(unit u) returns bool + /** This is used as dummy in the GroupEnum calls and should not be used */ constant DUMMY_GROUP = CreateGroup() // ====Callback stack for nested usage==== ForGroupCallback array tempCallbacks +ForGroupCallbackUntil array tempCallbacksUntil +int array callbackMode +int array countLimits +int array countIters +bool array stopRequested var tempCallbacksCount = 0 -var maxCount = INT_MAX -var iterCount = 0 constant filter = Filter(() -> filterCallback(GetFilterUnit())) +constant MODE_NORMAL = 0 +constant MODE_COUNTED = 1 +constant MODE_UNTIL = 2 function filterCallback(unit filter) - if iterCount < maxCount + let idx = tempCallbacksCount - 1 + let mode = callbackMode[idx] + if mode == MODE_NORMAL currentCallback().callback(filter) - iterCount++ + else if mode == MODE_COUNTED + if countIters[idx] < countLimits[idx] + currentCallback().callback(filter) + countIters[idx]++ + else if not stopRequested[idx] + if not currentCallbackUntil().callback(filter) + stopRequested[idx] = true function pushCallback(ForGroupCallback c) - tempCallbacks[tempCallbacksCount] = c + let idx = tempCallbacksCount + tempCallbacks[idx] = c + callbackMode[idx] = MODE_NORMAL + tempCallbacksCount++ + +function pushCallbackUntil(ForGroupCallbackUntil c) + let idx = tempCallbacksCount + tempCallbacksUntil[idx] = c + callbackMode[idx] = MODE_UNTIL + stopRequested[idx] = false + tempCallbacksCount++ + +function pushCallbackCounted(ForGroupCallback c, int count) + let idx = tempCallbacksCount + tempCallbacks[idx] = c + callbackMode[idx] = MODE_COUNTED + countLimits[idx] = count + countIters[idx] = 0 tempCallbacksCount++ - iterCount = 0 - maxCount = INT_MAX -function popCallback() +function popCallback(bool destroyCallback) DUMMY_GROUP.clear() tempCallbacksCount-- - destroy tempCallbacks[tempCallbacksCount] + let idx = tempCallbacksCount + if destroyCallback + if callbackMode[idx] == MODE_UNTIL + destroy tempCallbacksUntil[idx] + else + destroy tempCallbacks[idx] function currentCallback() returns ForGroupCallback return tempCallbacks[tempCallbacksCount - 1] + +function currentCallbackUntil() returns ForGroupCallbackUntil + return tempCallbacksUntil[tempCallbacksCount - 1] // ====Stack end==== /** Executes the given closure for every unit in this group, @@ -52,44 +93,41 @@ public function group.forEachIn(ForGroupCallback cb) public function forUnitsOfType(string unitname, ForGroupCallback c) pushCallback(c) GroupEnumUnitsOfType(DUMMY_GROUP, unitname, filter) - popCallback() + popCallback(true) /** Executes the given closure for every unit of the given player. Cancels itself after *count* iterations */ public function forUnitsOfTypeCounted(string unitname, int count, ForGroupCallback c) - pushCallback(c) - maxCount = count + pushCallbackCounted(c, count) GroupEnumUnitsOfType(DUMMY_GROUP, unitname, filter) - popCallback() + popCallback(true) /** Executes the given closure for every unit of the given player */ public function forUnitsOfPlayer(player p, ForGroupCallback c) pushCallback(c) GroupEnumUnitsOfPlayer(DUMMY_GROUP, p, filter) - popCallback() + popCallback(true) /** Executes the given closure for every existing unit */ public function forUnitsAll(ForGroupCallback c) for i = 0 to bj_MAX_PLAYER_SLOTS - 1 pushCallback(c) GroupEnumUnitsOfPlayer(DUMMY_GROUP, players[i], filter) - DUMMY_GROUP.clear() - tempCallbacksCount-- + popCallback(false) destroy c /** Executes the given closure for every unit in the given rect */ public function forUnitsInRect(rect r, ForGroupCallback c) pushCallback(c) GroupEnumUnitsInRect(DUMMY_GROUP, r, filter) - popCallback() + popCallback(true) /** Executes the given closure for every unit in the given rect. Cancels itself after *count* iterations */ public function forUnitsInRectCounted(rect r, int count, ForGroupCallback c) - pushCallback(c) - maxCount = count + pushCallbackCounted(c, count) GroupEnumUnitsInRect(DUMMY_GROUP, r, filter) - popCallback() + popCallback(true) /** Executes the given closure for every unit in range of the given position */ public function forUnitsInRange(vec2 pos, real radius, ForGroupCallback c) @@ -104,25 +142,24 @@ public function forUnitsInRange(vec2 pos, real radius, bool collisionSizeFilteri for u from ENUM_GROUP if IsUnitInRangeXY(u, pos.x, pos.y, radius) c.callback(u) - popCallback() + popCallback(true) else pushCallback(c) GroupEnumUnitsInRange(DUMMY_GROUP, pos.x, pos.y, radius, filter) - popCallback() + popCallback(true) /** Executes the given closure for every unit in range of the given position Cancels itself after *count* iterations */ public function forUnitsInRangeCounted(vec2 pos, real radius, int count, ForGroupCallback c) - pushCallback(c) - maxCount = count + pushCallbackCounted(c, count) GroupEnumUnitsInRange(DUMMY_GROUP, pos.x, pos.y, radius, filter) - popCallback() + popCallback(true) /** Executes the given closure for every unit selected by the given player */ public function forUnitsSelected(player p, ForGroupCallback c) pushCallback(c) GroupEnumUnitsSelected(DUMMY_GROUP, p, filter) - popCallback() + popCallback(true) /** Executes the given closure for the closest unit inside the given range of the given position, matching the provided filter. If there is no unit in range, the closure will be run with "null" */ @@ -137,7 +174,72 @@ public function forNearestUnit(vec2 pos, real range, filterfunc filter, ForGroup nearest = u bestDist = distSq c.callback(nearest) - popCallback() + popCallback(true) + +/** Executes the given closure for every unit in this group, + removing the units from the group as processed. + Return true to continue iteration, false to stop. */ +public function group.forEachFromUntil(ForGroupCallbackUntil cb) + while this.hasNext() + if not cb.callback(this.next()) + break + destroy cb + +/** Executes the given closure for every unit in this group, + keeping all units in the group. + Return true to continue iteration, false to stop. */ +public function group.forEachInUntil(ForGroupCallbackUntil cb) + let itr = this.iterator() + while itr.hasNext() + if not cb.callback(itr.next()) + break + itr.close() + destroy cb + +/** Executes the given closure for every unit of the given type. + Return true to continue iteration, false to stop callback invocation. */ +public function forUnitsOfTypeUntil(string unitname, ForGroupCallbackUntil c) + pushCallbackUntil(c) + GroupEnumUnitsOfType(DUMMY_GROUP, unitname, filter) + popCallback(true) + +/** Executes the given closure for every unit of the given player. + Return true to continue iteration, false to stop callback invocation. */ +public function forUnitsOfPlayerUntil(player p, ForGroupCallbackUntil c) + pushCallbackUntil(c) + GroupEnumUnitsOfPlayer(DUMMY_GROUP, p, filter) + popCallback(true) + +/** Executes the given closure for every existing unit. + Return true to continue iteration, false to stop callback invocation. */ +public function forUnitsAllUntil(ForGroupCallbackUntil c) + pushCallbackUntil(c) + for i = 0 to bj_MAX_PLAYER_SLOTS - 1 + GroupEnumUnitsOfPlayer(DUMMY_GROUP, players[i], filter) + if stopRequested[tempCallbacksCount - 1] + break + popCallback(true) + +/** Executes the given closure for every unit in the given rect. + Return true to continue iteration, false to stop callback invocation. */ +public function forUnitsInRectUntil(rect r, ForGroupCallbackUntil c) + pushCallbackUntil(c) + GroupEnumUnitsInRect(DUMMY_GROUP, r, filter) + popCallback(true) + +/** Executes the given closure for every unit in range of the given position. + Return true to continue iteration, false to stop callback invocation. */ +public function forUnitsInRangeUntil(vec2 pos, real radius, ForGroupCallbackUntil c) + pushCallbackUntil(c) + GroupEnumUnitsInRange(DUMMY_GROUP, pos.x, pos.y, radius, filter) + popCallback(true) + +/** Executes the given closure for every unit selected by the given player. + Return true to continue iteration, false to stop callback invocation. */ +public function forUnitsSelectedUntil(player p, ForGroupCallbackUntil c) + pushCallbackUntil(c) + GroupEnumUnitsSelected(DUMMY_GROUP, p, filter) + popCallback(true) // Destructables // ====Callback stack for nested usage==== From 0299f8425250d1ef96856cf1d06324ce5caf4ee6 Mon Sep 17 00:00:00 2001 From: Frotty Date: Tue, 17 Feb 2026 11:25:28 +0100 Subject: [PATCH 06/10] Update ClosureEvents.wurst --- wurst/closures/ClosureEvents.wurst | 74 +++++++++++++++--------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/wurst/closures/ClosureEvents.wurst b/wurst/closures/ClosureEvents.wurst index 19dcc9115..966aa4bf2 100644 --- a/wurst/closures/ClosureEvents.wurst +++ b/wurst/closures/ClosureEvents.wurst @@ -187,39 +187,40 @@ public abstract class EventListener // Unit Listeners if trigUnit != null let index = trigUnit.getIndex() - if fireEvents(trigUnit) and index > 0 and unitListenersFirsts[index] != null + if index > 0 var listener = unitListenersFirsts[index] - while listener != null - let nextListener = listener.next - if listener.eventId == id - listener.onEvent() - listener = nextListener + if listener != null and fireEvents(trigUnit) + while listener != null + let nextListener = listener.next + if listener.eventId == id + listener.onEvent() + listener = nextListener // Global Listeners - if generalListenersFirsts[id] != null - var listener = generalListenersFirsts[id] - while listener != null - let nextListener = listener.next - listener.onEvent() - listener = nextListener + var globalListener = generalListenersFirsts[id] + if globalListener != null + while globalListener != null + let nextListener = globalListener.next + globalListener.onEvent() + globalListener = nextListener static function onSpellEffect() let trigUnit = GetTriggerUnit() let abilId = GetSpellAbilityId() + let caster = GetSpellAbilityUnit() let index = trigUnit.getIndex() - if castMapCasters[index] != null - var listener = castMapCasters[index] - while listener != null - let nextListener = listener.next - if listener.abilId == -1 or listener.abilId == abilId - listener.fire(GetSpellAbilityUnit()) - listener = nextListener - if castMap.has(abilId) - var listener = castMap.get(abilId) - while listener != null - let nextListener = listener.next - if listener.eventUnit == null or listener.eventUnit == trigUnit - listener.fire(GetSpellAbilityUnit()) - listener = nextListener + var listener = castMapCasters[index] + while listener != null + let nextListener = listener.next + if listener.abilId == -1 or listener.abilId == abilId + listener.fire(caster) + listener = nextListener + + listener = castMap.get(abilId) + while listener != null + let nextListener = listener.next + if listener.eventUnit == null or listener.eventUnit == trigUnit + listener.fire(caster) + listener = nextListener ondestroy if uid < 0 @@ -240,7 +241,6 @@ public abstract class EventListener next = null prev = null -let unitTrig = CreateTrigger() let leaveTrig = CreateTrigger() let keyTrig = CreateTrigger() @@ -257,10 +257,16 @@ function registerEventId(eventid evnt) returns int let eventId = evnt.getHandleId() eventTypeCounter++ eventidToIndex[eventId] = eventTypeCounter - if evnt.isPlayerunitEvent() + if evnt == EVENT_UNIT_DAMAGED + eventidToIndex[EVENT_PLAYER_UNIT_DAMAGED.getHandleId()] = eventTypeCounter + registerPlayerUnitEvent(EVENT_PLAYER_UNIT_DAMAGED, function EventListener.generalEventCallback) + else if evnt == EVENT_PLAYER_UNIT_DAMAGED + eventidToIndex[EVENT_UNIT_DAMAGED.getHandleId()] = eventTypeCounter + registerPlayerUnitEvent(EVENT_PLAYER_UNIT_DAMAGED, function EventListener.generalEventCallback) + else if evnt.isPlayerunitEvent() registerPlayerUnitEvent(ConvertPlayerUnitEvent(eventId), function EventListener.generalEventCallback) - else if evnt != EVENT_UNIT_DAMAGED and evnt != EVENT_PLAYER_LEAVE and evnt != EVENT_PLAYER_CHAT_FILTER and not evnt.isKeyboardEvent() and not evnt.isMouseEvent() - error("registering handleid: " + eventId.toString() + " non-playerunitevent. Except EVENT_UNIT_DAMAGED and EVENT_PLAYER_LEAVE these are not supported right now.") + else if evnt != EVENT_PLAYER_LEAVE and evnt != EVENT_PLAYER_CHAT_FILTER and not evnt.isKeyboardEvent() and not evnt.isMouseEvent() + error("registering handleid: " + eventId.toString() + " non-playerunitevent. Except EVENT_PLAYER_LEAVE these are not supported right now.") if evnt.isMouseEvent() and not EventListener.useMouseEvents EventListener.useMouseEvents = true for i = 0 to bj_MAX_PLAYERS - 1 @@ -269,10 +275,6 @@ function registerEventId(eventid evnt) returns int ..registerPlayerEvent(players[i], EVENT_PLAYER_MOUSE_MOVE) return eventTypeCounter -function registerEventsForUnit(unit u) - if fireEvents(u) - unitTrig.registerUnitEvent(u, EVENT_UNIT_DAMAGED) - public function unregisterEventsForUnit(unit u) if fireEvents(u) let index = u.getIndex() @@ -298,12 +300,10 @@ public function unregisterEvents(int id) init - // Un/Register Events when unit enters map - onUnitIndex(() -> registerEventsForUnit(getIndexingUnit())) + // Clean up per-unit listener lists when units are deindexed. onUnitDeindex(() -> unregisterEventsForUnit(getIndexingUnit())) nullTimer() -> - unitTrig.addAction(() -> EventListener.generalEventCallback()) leaveTrig.addAction(() -> EventListener.generalEventCallback()) keyTrig.addAction(() -> EventListener.generalEventCallback()) From e79d8694793fc8583e8cdfd9b5a7f747814d17e2 Mon Sep 17 00:00:00 2001 From: Frotty Date: Tue, 17 Feb 2026 11:37:41 +0100 Subject: [PATCH 07/10] more micro opts --- wurst/_handles/Trigger.wurst | 3 ++- wurst/event/DamageEvent.wurst | 6 ++++-- wurst/event/OnUnitEnterLeave.wurst | 4 +++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/wurst/_handles/Trigger.wurst b/wurst/_handles/Trigger.wurst index b624b456c..4f8d714aa 100644 --- a/wurst/_handles/Trigger.wurst +++ b/wurst/_handles/Trigger.wurst @@ -76,7 +76,8 @@ public function trigger.getExecCount() returns int return GetTriggerExecCount(this) public function trigger.registerAnyUnitEvent(playerunitevent whichEvent) - TriggerRegisterAnyUnitEventBJ(this, whichEvent) + for i = 0 to bj_MAX_PLAYER_SLOTS - 1 + TriggerRegisterPlayerUnitEvent(this, Player(i), whichEvent, null) public function trigger.registerDeathEvent(widget whichWidget) returns event return TriggerRegisterDeathEvent(this, whichWidget) diff --git a/wurst/event/DamageEvent.wurst b/wurst/event/DamageEvent.wurst index cde0f1aea..72659f943 100644 --- a/wurst/event/DamageEvent.wurst +++ b/wurst/event/DamageEvent.wurst @@ -279,7 +279,8 @@ public class DamageEvent else if listener.prev != null listener.prev.next = listener.next - listener.next.prev = listener.prev + if listener.next != null + listener.next.prev = listener.prev /** Adds a damage event listener that fires before any damage reduction is applied (such as armor). If The order of firing is important, use addListener(priority, listener) */ @@ -315,7 +316,8 @@ public class DamageEvent else if listener.prev != null listener.prev.next = listener.next - listener.next.prev = listener.prev + if listener.next != null + listener.next.prev = listener.prev /* GETTERS */ /** Returns the id of the damage instance being currently fired */ diff --git a/wurst/event/OnUnitEnterLeave.wurst b/wurst/event/OnUnitEnterLeave.wurst index 1f564586c..b540c2252 100644 --- a/wurst/event/OnUnitEnterLeave.wurst +++ b/wurst/event/OnUnitEnterLeave.wurst @@ -77,7 +77,9 @@ init // Process preplaced units preplacedUnits.enumUnitsInRect(boundRect) - ForGroup(preplacedUnits, () -> prepareUnit(GetEnumUnit())) + let count = preplacedUnits.size() + for i = 0 to count - 1 + prepareUnit(preplacedUnits.get(i)) preplacedUnits..clear()..destr() @compiletime function generateAbility() From 0518ed9f2e3d7a7fc09134ebc1463c75ed13913a Mon Sep 17 00:00:00 2001 From: Frotty Date: Tue, 17 Feb 2026 11:56:07 +0100 Subject: [PATCH 08/10] Update PrimitivesTests.wurst --- wurst/_handles/primitives/PrimitivesTests.wurst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wurst/_handles/primitives/PrimitivesTests.wurst b/wurst/_handles/primitives/PrimitivesTests.wurst index 1d71e1beb..6de2d19cb 100644 --- a/wurst/_handles/primitives/PrimitivesTests.wurst +++ b/wurst/_handles/primitives/PrimitivesTests.wurst @@ -45,9 +45,9 @@ function testBoolean() @Test function testArrayLength() - let x = [1, 2, 3] - print("length: " + x.length.toString()) - x.length.assertEquals(3) + let _x = [1, 2, 3] + print("length: " + _x.length.toString()) + _x.length.assertEquals(3) @Test function testParity() From 5a04fdf315813ba6e48eedc3a94d148a5c7c289b Mon Sep 17 00:00:00 2001 From: Frotty Date: Sun, 1 Mar 2026 14:57:24 +0100 Subject: [PATCH 09/10] some missing extension functions --- wurst/_handles/CommonNativeExtensions.wurst | 280 ++++++++++++++++++++ wurst/_handles/Force.wurst | 4 + wurst/_handles/Group.wurst | 4 + wurst/_handles/Image.wurst | 6 + wurst/_handles/Item.wurst | 13 + wurst/_handles/Quest.wurst | 5 +- wurst/_handles/Rect.wurst | 18 ++ wurst/_handles/Region.wurst | 14 + wurst/_handles/Sound.wurst | 45 ++++ wurst/_handles/Trigger.wurst | 13 + wurst/_handles/Unit.wurst | 128 ++++++++- wurst/_handles/Widget.wurst | 4 + wurst/_handles/_Handles.wurst | 1 + 13 files changed, 533 insertions(+), 2 deletions(-) create mode 100644 wurst/_handles/CommonNativeExtensions.wurst diff --git a/wurst/_handles/CommonNativeExtensions.wurst b/wurst/_handles/CommonNativeExtensions.wurst new file mode 100644 index 000000000..171dd94bd --- /dev/null +++ b/wurst/_handles/CommonNativeExtensions.wurst @@ -0,0 +1,280 @@ +package CommonNativeExtensions +import NoWurst +import Annotations +import Vectors + +public function gametype.setGameTypeSupported(boolean value) + SetGameTypeSupported(this, value) + +public function mapflag.setMapFlag(boolean value) + SetMapFlag(this, value) + +public function placement.setGamePlacement() + SetGamePlacement(this) + +public function gamespeed.setGameSpeed() + SetGameSpeed(this) + +public function gamedifficulty.setGameDifficulty() + SetGameDifficulty(this) + +public function mapdensity.setResourceDensity() + SetResourceDensity(this) + +public function mapdensity.setCreatureDensity() + SetCreatureDensity(this) + +public function gametype.isGameTypeSupported() returns boolean + return IsGameTypeSupported(this) + +public function mapflag.isMapFlagSet() returns boolean + return IsMapFlagSet(this) + +@deprecated("Use vec2.rectFrom(vec2) to avoid location handles.") +public function location.rectFromLoc(location max) returns rect + return RectFromLoc(this, max) + +public function vec2.rectFrom(vec2 max) returns rect + return Rect(this.x, this.y, max.x, max.y) + +public function conditionfunc.destroyCondition() + DestroyCondition(this) + +public function filterfunc.destroyFilter() + DestroyFilter(this) + +@deprecated("Use player.hasVisibility(vec2) or vec2.isVisibleToPlayer(player).") +public function location.isLocationVisibleToPlayer(player whichPlayer) returns boolean + return IsLocationVisibleToPlayer(this, whichPlayer) + +@deprecated("Use vec2.isFoggedToPlayer(player) to avoid location handles.") +public function location.isLocationFoggedToPlayer(player whichPlayer) returns boolean + return IsLocationFoggedToPlayer(this, whichPlayer) + +@deprecated("Use vec2.isMaskedToPlayer(player) to avoid location handles.") +public function location.isLocationMaskedToPlayer(player whichPlayer) returns boolean + return IsLocationMaskedToPlayer(this, whichPlayer) + +public function vec2.isVisibleToPlayer(player whichPlayer) returns boolean + return IsVisibleToPlayer(this.x, this.y, whichPlayer) + +public function vec2.isFoggedToPlayer(player whichPlayer) returns boolean + return IsFoggedToPlayer(this.x, this.y, whichPlayer) + +public function vec2.isMaskedToPlayer(player whichPlayer) returns boolean + return IsMaskedToPlayer(this.x, this.y, whichPlayer) + +public function vec2.pingMinimap(real duration) + PingMinimap(this.x, this.y, duration) + +public function vec2.pingMinimapEx(real duration, integer red, integer green, integer blue, boolean extraEffects) + PingMinimapEx(this.x, this.y, duration, red, green, blue, extraEffects) + +public function vec2.createMinimapIcon(integer red, integer green, integer blue, string pingPath, fogstate fogVisibility) returns minimapicon + return CreateMinimapIcon(this.x, this.y, red, green, blue, pingPath, fogVisibility) + +public function vec2.terrainDeformRipple(real radius, real depth, integer duration, integer count, real spaceWaves, real timeWaves, real radiusStartPct, boolean limitNeg) returns terraindeformation + return TerrainDeformRipple(this.x, this.y, radius, depth, duration, count, spaceWaves, timeWaves, radiusStartPct, limitNeg) + +public function vec2.terrainDeformWave(vec2 direction, real distance, real speed, real radius, real depth, integer trailTime, integer count) returns terraindeformation + return TerrainDeformWave(this.x, this.y, direction.x, direction.y, distance, speed, radius, depth, trailTime, count) + +public function vec2.terrainDeformRandom(real radius, real minDelta, real maxDelta, integer duration, integer updateInterval) returns terraindeformation + return TerrainDeformRandom(this.x, this.y, radius, minDelta, maxDelta, duration, updateInterval) + +public function vec2.getTerrainCliffLevel() returns integer + return GetTerrainCliffLevel(this.x, this.y) + +public function vec2.createUbersplat(string name, integer red, integer green, integer blue, integer alpha, boolean forcePaused, boolean noBirthTime) returns ubersplat + return CreateUbersplat(this.x, this.y, name, red, green, blue, alpha, forcePaused, noBirthTime) + +public function vec2.isPointBlighted() returns boolean + return IsPointBlighted(this.x, this.y) + +public function vec2.setDoodadAnimation(real radius, integer doodadID, boolean nearestOnly, string animName, boolean animRandom) + SetDoodadAnimation(this.x, this.y, radius, doodadID, nearestOnly, animName, animRandom) + +public function version.versionCompatible() returns boolean + return VersionCompatible(this) + +public function version.versionSupported() returns boolean + return VersionSupported(this) + +public function race.setCampaignMenuRace() + SetCampaignMenuRace(this) + +public function fgamestate.setFloatGameState(real value) + SetFloatGameState(this, value) + +public function fgamestate.getFloatGameState() returns real + return GetFloatGameState(this) + +public function igamestate.setIntegerGameState(integer value) + SetIntegerGameState(this, value) + +public function igamestate.getIntegerGameState() returns integer + return GetIntegerGameState(this) + +public function gamedifficulty.setDefaultDifficulty() + SetDefaultDifficulty(this) + +public function unitpool.destroyUnitPool() + DestroyUnitPool(this) + +public function unitpool.unitPoolAddUnitType(integer unitId, real weight) + UnitPoolAddUnitType(this, unitId, weight) + +public function unitpool.unitPoolRemoveUnitType(integer unitId) + UnitPoolRemoveUnitType(this, unitId) + +public function unitpool.placeRandomUnit(player forWhichPlayer, real x, real y, real facing) returns unit + return PlaceRandomUnit(this, forWhichPlayer, x, y, facing) + +public function unitpool.placeRandomUnit(player forWhichPlayer, vec2 pos, real facing) returns unit + return PlaceRandomUnit(this, forWhichPlayer, pos.x, pos.y, facing) + +public function itempool.destroyItemPool() + DestroyItemPool(this) + +public function itempool.itemPoolAddItemType(integer itemId, real weight) + ItemPoolAddItemType(this, itemId, weight) + +public function itempool.itemPoolRemoveItemType(integer itemId) + ItemPoolRemoveItemType(this, itemId) + +public function itempool.placeRandomItem(real x, real y) returns item + return PlaceRandomItem(this, x, y) + +public function itempool.placeRandomItem(vec2 pos) returns item + return PlaceRandomItem(this, pos.x, pos.y) + +public function itemtype.chooseRandomItemEx(integer level) returns integer + return ChooseRandomItemEx(this, level) + +@deprecated("Use vec2.createMinimapIcon(...) to avoid location handles.") +public function location.createMinimapIconAtLoc(integer red, integer green, integer blue, string pingPath, fogstate fogVisibility) returns minimapicon + return CreateMinimapIconAtLoc(this, red, green, blue, pingPath, fogVisibility) + +public function minimapicon.destroyMinimapIcon() + DestroyMinimapIcon(this) + +public function minimapicon.setMinimapIconVisible(boolean visible) + SetMinimapIconVisible(this, visible) + +public function minimapicon.setMinimapIconOrphanDestroy(boolean doDestroy) + SetMinimapIconOrphanDestroy(this, doDestroy) + +public function defeatcondition.destroyDefeatCondition() + DestroyDefeatCondition(this) + +public function defeatcondition.defeatConditionSetDescription(string description) + DefeatConditionSetDescription(this, description) + +public function leaderboard.destroyLeaderboard() + DestroyLeaderboard(this) + +public function leaderboard.leaderboardDisplay(boolean show) + LeaderboardDisplay(this, show) + +public function leaderboard.isLeaderboardDisplayed() returns boolean + return IsLeaderboardDisplayed(this) + +public function leaderboard.leaderboardGetItemCount() returns integer + return LeaderboardGetItemCount(this) + +public function leaderboard.leaderboardSetSizeByItemCount(integer count) + LeaderboardSetSizeByItemCount(this, count) + +public function leaderboard.leaderboardAddItem(string label, integer value, player p) + LeaderboardAddItem(this, label, value, p) + +public function leaderboard.leaderboardRemoveItem(integer index) + LeaderboardRemoveItem(this, index) + +public function leaderboard.leaderboardRemovePlayerItem(player p) + LeaderboardRemovePlayerItem(this, p) + +public function leaderboard.leaderboardClear() + LeaderboardClear(this) + +public function leaderboard.leaderboardSortItemsByValue(boolean ascending) + LeaderboardSortItemsByValue(this, ascending) + +public function leaderboard.leaderboardSortItemsByPlayer(boolean ascending) + LeaderboardSortItemsByPlayer(this, ascending) + +public function leaderboard.leaderboardSortItemsByLabel(boolean ascending) + LeaderboardSortItemsByLabel(this, ascending) + +public function leaderboard.leaderboardHasPlayerItem(player p) returns boolean + return LeaderboardHasPlayerItem(this, p) + +public function leaderboard.leaderboardGetPlayerIndex(player p) returns integer + return LeaderboardGetPlayerIndex(this, p) + +public function leaderboard.leaderboardSetLabel(string label) + LeaderboardSetLabel(this, label) + +public function leaderboard.leaderboardGetLabelText() returns string + return LeaderboardGetLabelText(this) + +public function leaderboard.leaderboardSetLabelColor(integer red, integer green, integer blue, integer alpha) + LeaderboardSetLabelColor(this, red, green, blue, alpha) + +public function leaderboard.leaderboardSetValueColor(integer red, integer green, integer blue, integer alpha) + LeaderboardSetValueColor(this, red, green, blue, alpha) + +public function leaderboard.leaderboardSetStyle(boolean showLabel, boolean showNames, boolean showValues, boolean showIcons) + LeaderboardSetStyle(this, showLabel, showNames, showValues, showIcons) + +public function leaderboard.leaderboardSetItemValue(integer whichItem, integer val) + LeaderboardSetItemValue(this, whichItem, val) + +public function leaderboard.leaderboardSetItemLabel(integer whichItem, string val) + LeaderboardSetItemLabel(this, whichItem, val) + +public function leaderboard.leaderboardSetItemStyle(integer whichItem, boolean showLabel, boolean showValue, boolean showIcon) + LeaderboardSetItemStyle(this, whichItem, showLabel, showValue, showIcon) + +public function leaderboard.leaderboardSetItemLabelColor(integer whichItem, integer red, integer green, integer blue, integer alpha) + LeaderboardSetItemLabelColor(this, whichItem, red, green, blue, alpha) + +public function leaderboard.leaderboardSetItemValueColor(integer whichItem, integer red, integer green, integer blue, integer alpha) + LeaderboardSetItemValueColor(this, whichItem, red, green, blue, alpha) + +@deprecated("Use camerasetup.getDestPosition() from package Camera.") +public function camerasetup.cameraSetupGetDestPositionLoc() returns location + return CameraSetupGetDestPositionLoc(this) + +public function camerasetup.cameraSetupSetLabel(string label) + BlzCameraSetupSetLabel(this, label) + +public function camerasetup.cameraSetupGetLabel() returns string + return BlzCameraSetupGetLabel(this) + +public function volumegroup.volumeGroupSetVolume(real scale) + VolumeGroupSetVolume(this, scale) + +public function terraindeformation.terrainDeformStop(integer duration) + TerrainDeformStop(this, duration) + +public function ubersplat.destroyUbersplat() + DestroyUbersplat(this) + +public function ubersplat.resetUbersplat() + ResetUbersplat(this) + +public function ubersplat.finishUbersplat() + FinishUbersplat(this) + +public function ubersplat.showUbersplat(boolean flag) + ShowUbersplat(this, flag) + +public function ubersplat.setUbersplatRender(boolean flag) + SetUbersplatRender(this, flag) + +public function ubersplat.setUbersplatRenderAlways(boolean flag) + SetUbersplatRenderAlways(this, flag) + +public function commandbuttoneffect.destroyCommandButtonEffect() + DestroyCommandButtonEffect(this) diff --git a/wurst/_handles/Force.wurst b/wurst/_handles/Force.wurst index 5375414bc..ce602676c 100755 --- a/wurst/_handles/Force.wurst +++ b/wurst/_handles/Force.wurst @@ -85,3 +85,7 @@ public function force.next() returns player public function force.close() this.clear() this.destr() + +public function force.has(player whichPlayer) returns boolean + return BlzForceHasPlayer(this, whichPlayer) + diff --git a/wurst/_handles/Group.wurst b/wurst/_handles/Group.wurst index 521d1652c..2a6ab115e 100755 --- a/wurst/_handles/Group.wurst +++ b/wurst/_handles/Group.wurst @@ -154,3 +154,7 @@ public function group.next() returns unit public function group.close() this.clear() this.destr() + +public function group.forGroup(code callback) + ForGroup(this, callback) + diff --git a/wurst/_handles/Image.wurst b/wurst/_handles/Image.wurst index 13d9010e1..f9dcfcea3 100644 --- a/wurst/_handles/Image.wurst +++ b/wurst/_handles/Image.wurst @@ -79,3 +79,9 @@ public function image.remove() error("Nullpointer exeption by destroying an image") DestroyImage(this) +public function image.setImageRender(boolean flag) + SetImageRender(this, flag) + +public function image.setImageAboveWater(boolean flag, boolean useWaterAlpha) + SetImageAboveWater(this, flag, useWaterAlpha) + diff --git a/wurst/_handles/Item.wurst b/wurst/_handles/Item.wurst index 38940ab4a..6df370671 100644 --- a/wurst/_handles/Item.wurst +++ b/wurst/_handles/Item.wurst @@ -122,6 +122,12 @@ public function item.getIconPath() returns string public function item.setIconPath(string path) BlzSetItemIconPath(this, path) +public function item.getSkin() returns int + return BlzGetItemSkin(this) + +public function item.setSkin(int skinId) + BlzSetItemSkin(this, skinId) + // Item-Ability Get/Setters public function item.getAbilityByIndex(int index) returns ability return BlzGetItemAbilityByIndex(this, index) @@ -191,3 +197,10 @@ public function item.updateDetailsForPlayer(player p, string itemName, string it Returns false if no player is given. */ public function item.updateDetailsForAll(string itemName, string itemTooltip, string itemExtendedTooltip, string itemDesc, string itemIcon) returns bool return this.updateDetails(null, itemName, itemTooltip, itemExtendedTooltip, itemDesc, itemIcon) + +public function item.setItemDropID(integer unitId) + SetItemDropID(this, unitId) + +public function item.blzSetItemSkin(integer skinId) + BlzSetItemSkin(this, skinId) + diff --git a/wurst/_handles/Quest.wurst b/wurst/_handles/Quest.wurst index 55d73db02..27b49788d 100644 --- a/wurst/_handles/Quest.wurst +++ b/wurst/_handles/Quest.wurst @@ -63,7 +63,6 @@ public class Quest function isCompleted() returns boolean return q.isCompleted() - function getState() returns QuestState return qState @@ -84,3 +83,7 @@ public class Quest ondestroy q.remove() + +public function quest.setEnabled(boolean enabled) + QuestSetEnabled(this, enabled) + diff --git a/wurst/_handles/Rect.wurst b/wurst/_handles/Rect.wurst index d981a01b5..1cfb4f9a3 100644 --- a/wurst/_handles/Rect.wurst +++ b/wurst/_handles/Rect.wurst @@ -89,3 +89,21 @@ function rectTest() rekt.getCenterX().assertEquals(2) rekt.getCenterY().assertEquals(2) +public function rect.setRectFromLoc(location min, location max) + SetRectFromLoc(this, min, max) + +public function rect.moveRectToLoc(location newCenterLoc) + MoveRectToLoc(this, newCenterLoc) + +public function rect.enumDestructablesInRect(boolexpr filter, code actionFunc) + EnumDestructablesInRect(this, filter, actionFunc) + +public function rect.enumItemsInRect(boolexpr filter, code actionFunc) + EnumItemsInRect(this, filter, actionFunc) + +public function rect.addWeatherEffect(integer effectID) returns weathereffect + return AddWeatherEffect(this, effectID) + +public function rect.setDoodadAnimationRect(integer doodadID, string animName, boolean animRandom) + SetDoodadAnimationRect(this, doodadID, animName, animRandom) + diff --git a/wurst/_handles/Region.wurst b/wurst/_handles/Region.wurst index 523abbda4..19559d85c 100644 --- a/wurst/_handles/Region.wurst +++ b/wurst/_handles/Region.wurst @@ -1,6 +1,7 @@ package Region import NoWurst import Vectors +import Annotations public function vec2.isInRegion(region whichRegion) returns boolean return IsPointInRegion(whichRegion, this.x, this.y) @@ -22,3 +23,16 @@ public function region.clearCell(vec2 point) public function region.destr() RemoveRegion(this) + +@deprecated("Use region.addCell(vec2) to avoid location handles.") +public function region.regionAddCellAtLoc(location whichLocation) + RegionAddCellAtLoc(this, whichLocation) + +@deprecated("Use region.clearCell(vec2) to avoid location handles.") +public function region.regionClearCellAtLoc(location whichLocation) + RegionClearCellAtLoc(this, whichLocation) + +@deprecated("Use vec2.isInRegion(region) to avoid location handles.") +public function region.isLocationInRegion(location whichLocation) returns boolean + return IsLocationInRegion(this, whichLocation) + diff --git a/wurst/_handles/Sound.wurst b/wurst/_handles/Sound.wurst index 5a397fd74..0017f18a7 100644 --- a/wurst/_handles/Sound.wurst +++ b/wurst/_handles/Sound.wurst @@ -43,3 +43,48 @@ public function sound.getDuration() returns int public function sound.isPlaying() returns boolean return GetSoundIsPlaying(this) +public function sound.triggerWaitForSound(real offset) + TriggerWaitForSound(this, offset) + +public function sound.setSoundParamsFromLabel(string soundLabel) + SetSoundParamsFromLabel(this, soundLabel) + +public function sound.setSoundDistances(real minDist, real maxDist) + SetSoundDistances(this, minDist, maxDist) + +public function sound.setSoundConeOrientation(real x, real y, real z) + SetSoundConeOrientation(this, x, y, z) + +public function sound.setSoundPosition(real x, real y, real z) + SetSoundPosition(this, x, y, z) + +public function sound.setSoundVelocity(real x, real y, real z) + SetSoundVelocity(this, x, y, z) + +public function sound.attachSoundToUnit(unit whichUnit) + AttachSoundToUnit(this, whichUnit) + +public function sound.startSoundEx(boolean fadeIn) + StartSoundEx(this, fadeIn) + +public function sound.registerStackedSound(boolean byPosition, real rectwidth, real rectheight) + RegisterStackedSound(this, byPosition, rectwidth, rectheight) + +public function sound.unregisterStackedSound(boolean byPosition, real rectwidth, real rectheight) + UnregisterStackedSound(this, byPosition, rectwidth, rectheight) + +public function sound.setSoundFacialAnimationLabel(string animationLabel) returns boolean + return SetSoundFacialAnimationLabel(this, animationLabel) + +public function sound.setSoundFacialAnimationGroupLabel(string groupLabel) returns boolean + return SetSoundFacialAnimationGroupLabel(this, groupLabel) + +public function sound.setSoundFacialAnimationSetFilepath(string animationSetFilepath) returns boolean + return SetSoundFacialAnimationSetFilepath(this, animationSetFilepath) + +public function sound.setDialogueSpeakerNameKey(string speakerName) returns boolean + return SetDialogueSpeakerNameKey(this, speakerName) + +public function sound.setDialogueTextKey(string dialogueText) returns boolean + return SetDialogueTextKey(this, dialogueText) + diff --git a/wurst/_handles/Trigger.wurst b/wurst/_handles/Trigger.wurst index 4f8d714aa..f8fe4f99b 100644 --- a/wurst/_handles/Trigger.wurst +++ b/wurst/_handles/Trigger.wurst @@ -164,3 +164,16 @@ public function trigger.removeCondition(triggercondition condition) public function trigger.reset() ResetTrigger(this) + +public function trigger.registerVariableEvent(string varName, limitop opcode, real limitval) returns event + return TriggerRegisterVariableEvent(this, varName, opcode, limitval) + +public function trigger.registerCommandEvent(integer whichAbility, string order) returns event + return TriggerRegisterCommandEvent(this, whichAbility, order) + +public function trigger.registerUpgradeCommandEvent(integer whichUpgrade) returns event + return TriggerRegisterUpgradeCommandEvent(this, whichUpgrade) + +public function trigger.blzTriggerRegisterPlayerSyncEvent(player whichPlayer, string prefix, boolean fromServer) returns event + return BlzTriggerRegisterPlayerSyncEvent(this, whichPlayer, prefix, fromServer) + diff --git a/wurst/_handles/Unit.wurst b/wurst/_handles/Unit.wurst index 0078778fa..a788a9321 100644 --- a/wurst/_handles/Unit.wurst +++ b/wurst/_handles/Unit.wurst @@ -233,7 +233,6 @@ public function unit.getMissingHP() returns real public function unit.getMissingMana() returns real return this.getMaxMana() - this.getMana() - public function unit.getMoveSpeed() returns real return GetUnitMoveSpeed(this) @@ -936,3 +935,130 @@ public function unit.setFieldWeapon(unitweaponrealfield field, int weaponIndex, public function unit.setFieldWeapon(unitweaponstringfield field, int weaponIndex, string value) returns bool return BlzSetUnitWeaponStringField(this, field, weaponIndex, value) + +public function unit.reviveHeroLoc(location loc, boolean doEyecandy) returns boolean + return ReviveHeroLoc(this, loc, doEyecandy) + +public function unit.selectUnit(boolean flag) + SelectUnit(this, flag) + +public function unit.suspendDecay(boolean suspend) + UnitSuspendDecay(this, suspend) + +public function unit.removeBuffs(boolean removePositive, boolean removeNegative) + UnitRemoveBuffs(this, removePositive, removeNegative) + +public function unit.removeBuffsEx(boolean removePositive, boolean removeNegative, boolean magic, boolean physical, boolean timedLife, boolean aura, boolean autoDispel) + UnitRemoveBuffsEx(this, removePositive, removeNegative, magic, physical, timedLife, aura, autoDispel) + +public function unit.hasBuffsEx(boolean removePositive, boolean removeNegative, boolean magic, boolean physical, boolean timedLife, boolean aura, boolean autoDispel) returns boolean + return UnitHasBuffsEx(this, removePositive, removeNegative, magic, physical, timedLife, aura, autoDispel) + +public function unit.countBuffsEx(boolean removePositive, boolean removeNegative, boolean magic, boolean physical, boolean timedLife, boolean aura, boolean autoDispel) returns integer + return UnitCountBuffsEx(this, removePositive, removeNegative, magic, physical, timedLife, aura, autoDispel) + +public function unit.addSleep(boolean add) + UnitAddSleep(this, add) + +public function unit.addSleepPerm(boolean add) + UnitAddSleepPerm(this, add) + +public function unit.ignoreAlarm(boolean flag) returns boolean + return UnitIgnoreAlarm(this, flag) + +public function unit.setConstructionProgress(integer constructionPercentage) + UnitSetConstructionProgress(this, constructionPercentage) + +public function unit.setUpgradeProgress(integer upgradePercentage) + UnitSetUpgradeProgress(this, upgradePercentage) + +public function unit.pauseTimedLife(boolean flag) + UnitPauseTimedLife(this, flag) + +public function unit.setUsesAltIcon(boolean flag) + UnitSetUsesAltIcon(this, flag) + +public function unit.damagePoint(real delay, real radius, real x, real y, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, weapontype weaponType) returns boolean + return UnitDamagePoint(this, delay, radius, x, y, amount, attack, ranged, attackType, damageType, weaponType) + +public function unit.issuePointOrderLoc(string order, location whichLocation) returns boolean + return IssuePointOrderLoc(this, order, whichLocation) + +public function unit.issuePointOrderByIdLoc(integer order, location whichLocation) returns boolean + return IssuePointOrderByIdLoc(this, order, whichLocation) + +public function unit.issueInstantPointOrder(string order, real x, real y, widget instantTargetWidget) returns boolean + return IssueInstantPointOrder(this, order, x, y, instantTargetWidget) + +public function unit.issueInstantPointOrderById(integer order, real x, real y, widget instantTargetWidget) returns boolean + return IssueInstantPointOrderById(this, order, x, y, instantTargetWidget) + +public function unit.issueInstantTargetOrder(string order, widget targetWidget, widget instantTargetWidget) returns boolean + return IssueInstantTargetOrder(this, order, targetWidget, instantTargetWidget) + +public function unit.issueInstantTargetOrderById(integer order, widget targetWidget, widget instantTargetWidget) returns boolean + return IssueInstantTargetOrderById(this, order, targetWidget, instantTargetWidget) + +public function unit.issueBuildOrder(string unitToBuild, real x, real y) returns boolean + return IssueBuildOrder(this, unitToBuild, x, y) + +public function unit.issueBuildOrderById(integer unitId, real x, real y) returns boolean + return IssueBuildOrderById(this, unitId, x, y) + +public function unit.setResourceAmount(integer amount) + SetResourceAmount(this, amount) + +public function unit.addResourceAmount(integer amount) + AddResourceAmount(this, amount) + +public function unit.waygateSetDestination(real x, real y) + WaygateSetDestination(this, x, y) + +public function unit.waygateActivate(boolean activate) + WaygateActivate(this, activate) + +public function unit.setItemTypeSlots(integer slots) + SetItemTypeSlots(this, slots) + +public function unit.addIndicator(integer red, integer green, integer blue, integer alpha) + UnitAddIndicator(this, red, green, blue, alpha) + +public function unit.createMinimapIconOnUnit(integer red, integer green, integer blue, string pingPath, fogstate fogVisibility) returns minimapicon + return CreateMinimapIconOnUnit(this, red, green, blue, pingPath, fogVisibility) + +public function unit.setCameraTargetController(real xoffset, real yoffset, boolean inheritOrientation) + SetCameraTargetController(this, xoffset, yoffset, inheritOrientation) + +public function unit.setCameraOrientController(real xoffset, real yoffset) + SetCameraOrientController(this, xoffset, yoffset) + +public function unit.setFacingEx(real facingAngle) + BlzSetUnitFacingEx(this, facingAngle) + +public function unit.setSkin(integer skinId) + BlzSetUnitSkin(this, skinId) + +public function unit.queueImmediateOrderById(integer order) returns boolean + return BlzQueueImmediateOrderById(this, order) + +public function unit.queuePointOrderById(integer order, real x, real y) returns boolean + return BlzQueuePointOrderById(this, order, x, y) + +public function unit.queueTargetOrderById(integer order, widget targetWidget) returns boolean + return BlzQueueTargetOrderById(this, order, targetWidget) + +public function unit.queueInstantPointOrderById(integer order, real x, real y, widget instantTargetWidget) returns boolean + return BlzQueueInstantPointOrderById(this, order, x, y, instantTargetWidget) + +public function unit.queueInstantTargetOrderById(integer order, widget targetWidget, widget instantTargetWidget) returns boolean + return BlzQueueInstantTargetOrderById(this, order, targetWidget, instantTargetWidget) + +public function unit.queueBuildOrderById(integer unitId, real x, real y) returns boolean + return BlzQueueBuildOrderById(this, unitId, x, y) + +public function unit.clearOrders(boolean onlyQueued) + BlzUnitClearOrders(this, onlyQueued) + +public function unit.forceStopOrder(boolean clearQueue) + BlzUnitForceStopOrder(this, clearQueue) + diff --git a/wurst/_handles/Widget.wurst b/wurst/_handles/Widget.wurst index 61cbf2c7a..0f4efc008 100644 --- a/wurst/_handles/Widget.wurst +++ b/wurst/_handles/Widget.wurst @@ -23,3 +23,7 @@ public function widget.addEffect(string modelName, string attachment) returns ef /** Checks if the widget is alive by testing current life > .405 */ public function widget.isAliveTrick() returns bool return .405 < this.getLife() + +public function widget.addIndicator(integer red, integer green, integer blue, integer alpha) + AddIndicator(this, red, green, blue, alpha) + diff --git a/wurst/_handles/_Handles.wurst b/wurst/_handles/_Handles.wurst index 181f47fa0..551d6511d 100755 --- a/wurst/_handles/_Handles.wurst +++ b/wurst/_handles/_Handles.wurst @@ -5,6 +5,7 @@ import public _Primitives import public Ability import public Boolexpr import public Camera +import public CommonNativeExtensions import public Destructable import public Effect import public Fogmodifier From ce112d308a3e30959bdadace828315c9bcf718e2 Mon Sep 17 00:00:00 2001 From: Frotty Date: Sun, 1 Mar 2026 19:13:55 +0100 Subject: [PATCH 10/10] Create AGENTS.md --- AGENTS.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..cc4d9c9a8 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,22 @@ +# AGENTS.md + +## WurstScript Project Rules + +- Prefer extension functions over calling bare natives directly. +- Prefer chaining extension calls with the `..` cascade operator when it improves readability and keeps call chains efficient. +- Avoid `location` handles. Use `vec2`-based APIs instead. +- For sets of units, prefer `group`. +- For sets of players, prefer `force`. +- For arbitrary data collections, prefer `LinkedList`. +- Use the highest abstraction level that is practical: + - Example: prefer hashmap-style abstractions over raw hashtable usage when performance is not a critical hot path. +- In critical hot paths, choose the more performant lower-level approach. +- Use asset constants from asset packages instead of raw asset path strings. +- Follow WurstScript language rules strictly (e.g. no `continue`; use valid Wurst constructs only). + +## Guideline Priority + +When rules conflict: +1. Correctness +2. Performance requirements of the code path +3. Readability and abstraction level