/
DummyRecycler.wurst
138 lines (122 loc) · 4.32 KB
/
DummyRecycler.wurst
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package DummyRecycler
import NoWurst
import public Unit
import public Timer
import Basics
import ErrorHandling
import MapBounds
import AbilityObjEditing
import ObjectIds
import Colors
import Annotations
import UnitIds
import Icons
import ObjectIdGenerator
import LinkedList
import TypeCasting
import ClosureTimers
/** Id of the dummy unit */
public constant DUMMY_UNIT_ID = compiletime(UNIT_ID_GEN.next())
/** Id of the root ability
it makes unit:
1. not need to turn when spell or attack
2. can't move or turn by order like a building
3. but you can still set it's postion with code
4. the effect remains even if this ability is removed
*/
public constant ROOT_ENABLER = compiletime(ABIL_ID_GEN.next())
public constant DISABLE_AUTO_ACQUIRE_ATTACK_TARGETS_ABILITY_ID = compiletime(ABIL_ID_GEN.next())
constant DIFFERENT_ANGLES = 8
constant ANGLE_DEGREE = 360 / DIFFERENT_ANGLES
constant SAVED_UNITS_PER_ANGLE = 6
public class DummyRecycler
static LinkedList<unit> array angleQueues
static function get(vec2 pos, angle a) returns unit
let angleIndex = (a.degrees() % 360 / ANGLE_DEGREE).round() mod DIFFERENT_ANGLES
if angleQueues[angleIndex].size() > 0
return angleQueues[angleIndex].dequeue()..setXY(pos)..unpause()
else
return createDummy(pos, a)
static function recycle(unit u)
var smallestQueue = 0
for i = 1 to DIFFERENT_ANGLES - 1
if angleQueues[smallestQueue].size() > angleQueues[i].size()
smallestQueue = i
if angleQueues[smallestQueue].size() >= SAVED_UNITS_PER_ANGLE
u.remove()
else
angleQueues[smallestQueue].enqueue(u)
u..setXY(boundMax - vec2(16, 16))
..pause()
..setFacing((smallestQueue * ANGLE_DEGREE).asAngleDegrees())
..setScale(1)
..setVertexColor(COLOR_WHITE)
..setOwner(DUMMY_PLAYER, true)
static function recycle(unit u, real delay)
doAfter(delay) ->
DummyRecycler.recycle(u)
function createDummy(vec2 pos, angle facing) returns unit
let u = createUnit(DUMMY_PLAYER, DUMMY_UNIT_ID, pos, facing)
u..addAbility(HEIGHT_ENABLER)..removeAbility(HEIGHT_ENABLER)
..addAbility(ROOT_ENABLER)..removeAbility(ROOT_ENABLER)
..setXY(pos)..setFacing(facing)
return u
init
realToIndex(1)
for i = 0 to DIFFERENT_ANGLES - 1
DummyRecycler.angleQueues[i] = new LinkedList<unit>()
let facing = angle(i * ANGLE_DEGREE)
for j = 0 to SAVED_UNITS_PER_ANGLE - 1
let dummy = createDummy(boundMax - vec2(16, 16), facing)
DummyRecycler.angleQueues[i].enqueue(dummy)
@compiletime function generateDummyUnit()
new AbilityDefinitionRootAncients(ROOT_ENABLER)
new AbilityDefinitionPermanentInvisibility(DISABLE_AUTO_ACQUIRE_ATTACK_TARGETS_ABILITY_ID)
..presetAutoAcquireAttackTargets(_ -> false)
..presetDurationNormal(_ -> -1)
..presetDurationHero(_ -> -1)
new UnitDefinition(DUMMY_UNIT_ID, UnitIds.wisp)
..setName("Effect Dummy Unit")
..setUpgradesUsed("")
..setStructuresBuilt("")
..setManaRegeneration(0.1)
..setManaInitialAmount(1000)
..setManaMaximum(1000)
..setCollisionSize(0.0)
..setRace(Race.Commoner)
..setFoodCost(0)
..setArmorType(ArmorType.Divine)
..setIconGameInterface(Icons.bTNTemp)
..setSpeedBase(522)
..setModelFile("dummy.mdl")
..setAnimationBlendTimeseconds(0.0)
..setAnimationCastBackswing(0.0)
..setMaximumPitchAngledegrees(0.0)
..setMaximumRollAngledegrees(0.0)
..setArtSpecial("")
..setProjectileImpactZ(0.0)
..setProjectileLaunchZ(0.0)
..setNameEditorSuffix("(Basics)")
..setSightRadiusDay(1)
..setSightRadiusNight(1)
..setUnitClassification("_")
..setPropulsionWindowdegrees(1.0)
..setTooltipBasic("")
..setAttacksEnabled(AttacksEnabled.AttackOneOnly.toObjectInt())
..setAttack1AnimationBackswingPoint(0)
..setAttack1AnimationDamagePoint(0)
..setAttack1CooldownTime(0)
..setAttack1AttackType(AttackType.Unknown)
..setAttack1DamageBase(-1)
..setAttack1DamageNumberofDice(1)
..setAttack1DamageSidesperDie(1)
..setAttack1ProjectileSpeed(INT_MAX)
..setAttack1Range(INT_MAX)
..setAttack1TargetsAllowed(
commaList(TargetsAllowed.air, TargetsAllowed.debris, TargetsAllowed.ground, TargetsAllowed.invulnerable,
TargetsAllowed.item_t, TargetsAllowed.structure, TargetsAllowed.vulnerable, TargetsAllowed.ward))
..setAttack1WeaponSound(WeaponSound.Nothing)
..setAttack1WeaponType(WeaponType.Instant)
..setAcquisitionRange(INT_MAX.toReal())
..setNormalAbilities(
commaList(AbilityIds.invulnerable, AbilityIds.locust, DISABLE_AUTO_ACQUIRE_ATTACK_TARGETS_ABILITY_ID))