Name | Type | is_array | initial_value |
Abil_SheepStrike_DummyBar | unit | No | |
AfterDamageEvent | real | No | |
Angle_ofwaterPushUnit | real | No | |
Angle_ofwaterPushUnit_array | real | Yes | |
AOEDamageEvent | real | No | |
AOEDamageSource | unit | No | |
ARCANE_Damage_Left | real | No | |
ARCANE_Damage_LeftRight | real | No | |
ARCANE_Damage_Right | real | No | |
ArcaneMissileTimerCasting | timer | No | |
ArcaneTimerReal | real | No | 0.30 |
ArcaneVaultBox | unit | No | |
ArcaneVaultSpawdUnitProgBar | unit | No | |
ArcaneVaultSpawnedUnit | unit | No | |
ArcaneVaultSpawnedUnitPoint | location | No | |
ArcaneVaultSpawnedUnitType | unitcode | Yes | |
ArchmageModelDummy | unit | No | |
ArchmageSelectable | unit | No | |
ATTACK_TYPE_CHAOS | integer | No | |
ATTACK_TYPE_HERO | integer | No | |
ATTACK_TYPE_MAGIC | integer | No | |
ATTACK_TYPE_NORMAL | integer | No | |
ATTACK_TYPE_PIERCE | integer | No | |
ATTACK_TYPE_SIEGE | integer | No | |
ATTACK_TYPE_SPELLS | integer | No | |
AttackTypeDebugStr | string | Yes | |
AVATAR_Damage_o | integer | No | |
AvatarSpecalEfffectPotision | location | No | |
AvatarSpecialEffect | effect | No | |
BlizzardTimer | timer | No | |
BlizzRandomPoint | location | No | |
Book | unit | No | |
BookDeathtimer | timer | No | |
BookINtegerProb | integer | No | |
BookSpawnPoint | location | No | |
BookString | string | Yes | |
BookTextPoint | location | No | |
BookType | unitcode | Yes | |
CameraDistanceReal | real | No | |
CenterPoint | location | No | |
CinematicRemoveUnits | group | No | |
CinematicSkipped | boolean | No | |
CP_HiddenItems | item | Yes | |
CP_HiddenItemsIndex | integer | No | |
CP_Item | item | No | |
CP_Point | location | No | |
CP_Point_Array | location | Yes | |
CP_PointIsWalkable | boolean | No | |
CP_PointIsWalkable_Array | boolean | Yes | |
CP_PointIsWalkable_array | boolean | Yes | |
CP_Rect | rect | No | |
DaiseUnitsEnterd | integer | No | |
DaisiesBig | unit | No | |
DaisiesSizeREal | real | No | 100.00 |
DaisiesTarget | integer | No | |
DAMAGE_TYPE_ACID | integer | No | |
DAMAGE_TYPE_COLD | integer | No | |
DAMAGE_TYPE_DEATH | integer | No | |
DAMAGE_TYPE_DEFENSIVE | integer | No | |
DAMAGE_TYPE_DEMOLITION | integer | No | |
DAMAGE_TYPE_DISEASE | integer | No | |
DAMAGE_TYPE_DIVINE | integer | No | |
DAMAGE_TYPE_ENHANCED | integer | No | |
DAMAGE_TYPE_FIRE | integer | No | |
DAMAGE_TYPE_FORCE | integer | No | |
DAMAGE_TYPE_LIGHTNING | integer | No | |
DAMAGE_TYPE_MAGIC | integer | No | |
DAMAGE_TYPE_MIND | integer | No | |
DAMAGE_TYPE_NORMAL | integer | No | |
DAMAGE_TYPE_PLANT | integer | No | |
DAMAGE_TYPE_POISON | integer | No | |
DAMAGE_TYPE_SHADOW_STRIKE | integer | No | |
DAMAGE_TYPE_SLOW_POISON | integer | No | |
DAMAGE_TYPE_SONIC | integer | No | |
DAMAGE_TYPE_SPIRIT_LINK | integer | No | |
DAMAGE_TYPE_UNIVERSAL | integer | No | |
DAMAGE_TYPE_UNKNOWN | integer | No | |
DamageBlockingAbility | abilcode | No | |
DamageEvent | real | No | |
DamageEventAmount | real | No | |
DamageEventAOE | integer | No | |
DamageEventAOEGroup | group | No | |
DamageEventAttackT | integer | No | |
DamageEventDamageT | integer | No | |
DamageEventLevel | integer | No | |
DamageEventOverride | boolean | No | |
DamageEventPrevAmt | real | No | |
DamageEventPureAmt | real | No | |
DamageEventSource | unit | No | |
DamageEventsWasted | integer | No | |
DamageEventTarget | unit | No | |
DamageEventTrigger | trigger | No | |
DamageEventType | integer | No | |
DamageEventWeaponT | integer | No | |
DamageModifierEvent | real | No | |
DamageScalingWC3 | real | No | |
DamageTypeArcane | integer | No | |
DamageTypeBlocked | integer | No | |
DamageTypeCode | integer | No | |
DamageTypeCriticalStrike | integer | No | |
DamageTypeDebugStr | string | Yes | |
DamageTypeExplosive | integer | No | |
DamageTypeHeal | integer | No | |
DamageTypePure | integer | No | |
DamageTypePureExplosive | integer | No | |
DamageTypeReduced | integer | No | |
Dialog_Button_Toutorial_Play | button | No | |
Dialog_Button_Toutorial_Skip | button | No | |
Dialog_Toutorial | dialog | No | |
Distance_ofwaterPushUnit | real | No | |
divineShieldEffect | effect | No | |
DmgEvLife | real | No | |
DmgEvPrevLife | real | No | |
DmgEvRecursionLevel | integer | No | |
DmgEvRecursionN | integer | No | |
DmgEvRunning | boolean | No | |
DmgEvStarted | boolean | No | |
DmgEvTimer | timer | No | |
DmgEvTrig | trigger | No | |
DmgEvUnit | unit | No | |
DmgStr | string | No | |
DommyArcaneMPoint | location | No | |
DreadLOrd | unit | No | |
DruidBear | unit | No | |
DummyAoeTimer | timer | No | |
DummyArcaneAtkPoint | location | No | |
DummyArcaneM | unit | No | |
DummyFacing | unit | No | |
Effect_FireLEftRight | effect | No | |
Effect_FireRIGHT | effect | No | |
Effect_FreLEFT | effect | No | |
Effect_R | effect | No | |
Effect_WAterLEFT | effect | No | |
Effect_WaterRIGHT | effect | No | |
EffectArcaneLEFT | effect | No | |
EffectArcaneLEFTRIHGT | effect | No | |
EffectArcaneRIGHT | effect | No | |
EffectICELEFT | effect | No | |
EffectIceLEFTRIGHt | effect | No | |
EffectIceRGHT | effect | No | |
EnhancedDamageTarget | unit | No | |
ErrorMessage | string | No | |
ErrorPlayer | player | No | |
ErrorSound | sound | No | |
EVENT_MISSILE_COLLIDE_DEST | integer | No | |
EVENT_MISSILE_COLLIDE_UNIT | integer | No | |
EVENT_MISSILE_FINISH | integer | No | |
EVENT_MISSILE_NOTHING | integer | No | |
EVENT_MISSILE_PERIODIC | integer | No | |
EVENT_MISSILE_REMOVE | integer | No | |
Fase1ArcaneBlast | boolean | No | |
Fase1ArcaneExp | boolean | No | |
Fase1ArcaneMissiles | boolean | No | |
Fire_Burn_Dummy | unit | No | |
FIRE_Damage_Left | real | No | |
FIRE_Damage_Left_RightTrue | real | No | |
FIRE_Damage_LeftRight | real | No | |
FIRE_Damage_Right | real | No | |
Herolevelarkimage | integer | No | |
herolevelnanetto | integer | No | |
Herospawned | boolean | No | |
HornOfCenariusPed | unit | No | |
HornSound | sound | No | |
HornTimer | timer | No | |
HuntresSound | sound | Yes | |
HuntressSoundTimer | timer | No | |
ICE_Damage_Left | real | No | |
ICE_Damage_LeftRight | real | No | |
ICE_Damage_Right | real | No | |
IceLeftEffect | effect | No | |
IceWall_Temp_point | location | No | |
IceWallDestrMAtrix | destructable | Yes | |
IceWallIndex | integer | No | |
IceWallNumber | integer | No | |
IceWallProgressBarUnit | unit | Yes | |
IceWallRotateTimer | timer | No | |
IceWallUnit | unit | No | |
IceWallUnitFacingDeg | real | No | |
IOnCannonActive | boolean | No | |
IonCannonTimer | timer | No | |
IsDamageCode | boolean | No | |
IsDamageMelee | boolean | No | |
IsDamageRanged | boolean | No | |
IsDamageSpell | boolean | No | |
IsUnitBeingKnockedBack | boolean | Yes | |
K2DAmphibious | boolean | Yes | |
K2DAngle | real | Yes | |
K2DBounce | boolean | Yes | |
K2DCollision | real | Yes | |
K2DCos | real | Yes | |
K2DCosD1 | real | Yes | |
K2DCosD2 | real | Yes | |
K2DCosH | real | Yes | |
K2DDebrisKiller | unit | No | |
K2DDestRadius | real | Yes | |
K2DDistanceLeft | real | Yes | |
K2DFlying | boolean | Yes | |
K2DFreeze | boolean | Yes | |
K2DFriction | real | Yes | |
K2DFXModel | string | Yes | |
K2DFXRate | real | Yes | |
K2DFXTimeLeft | real | Yes | |
K2DHeight | real | Yes | |
K2DHeightThreshold | real | Yes | |
K2DImpact | trigger | Yes | |
K2DItem | item | No | |
K2DItemOffset | boolean | No | |
K2DItemsFound | boolean | No | |
K2DKillTrees | boolean | Yes | |
K2DLastX | real | Yes | |
K2DLastY | real | Yes | |
K2DMaxDestRadius | real | No | |
K2DMaxX | real | No | |
K2DMaxY | real | No | |
K2DMinX | real | No | |
K2DMinY | real | No | |
K2DNext | integer | Yes | |
K2DOverride | boolean | Yes | |
K2DPause | boolean | Yes | |
K2DPrev | integer | Yes | |
K2DRadius | integer | Yes | |
K2DRegion | rect | No | |
K2DSimple | boolean | Yes | |
K2DSin | real | Yes | |
K2DSinD1 | real | Yes | |
K2DSinD2 | real | Yes | |
K2DSinH | real | Yes | |
K2DSource | unit | Yes | |
K2DTimeLeft | real | Yes | |
K2DTimeout | real | No | |
K2DTimer | timer | No | |
K2DUnbiasedCollision | boolean | Yes | |
K2DVelocity | real | Yes | |
K2DX | real | No | |
K2DY | real | No | |
Knockback2DAmphibious | boolean | No | |
Knockback2DAngle | real | No | |
Knockback2DBounces | boolean | No | |
Knockback2DCollision | real | No | |
Knockback2DDefaultBounce | boolean | No | |
Knockback2DDefaultDestRadius | real | No | |
Knockback2DDefaultFriction | real | No | |
Knockback2DDefaultFX | string | No | |
Knockback2DDefaultFXRate | real | No | |
Knockback2DDefaultGravity | real | No | |
Knockback2DDefaultKillTrees | boolean | No | |
Knockback2DDefaultPause | boolean | No | |
Knockback2DDestRadius | real | No | |
Knockback2DDistance | real | No | |
Knockback2DFriction | real | No | |
Knockback2DFXRate | real | No | |
Knockback2DGravity | real | No | |
Knockback2DHeight | real | No | |
Knockback2DKillTrees | boolean | No | |
Knockback2DLoopFX | string | No | |
Knockback2DOnImpact | trigger | No | |
Knockback2DOverride | boolean | No | |
Knockback2DPause | boolean | No | |
Knockback2DRobustPathing | integer | No | |
Knockback2DSimple | boolean | No | |
Knockback2DSource | unit | No | |
Knockback2DTime | real | No | |
Knockback2DTreeOrDebris | string | No | |
Knockback2DUnbiasedCollision | boolean | No | |
Knockback2DUnit | unit | No | |
LastDamageHP | real | No | |
LastDmgPrevAmount | real | Yes | |
LastDmgPrevType | integer | Yes | |
LastDmgSource | unit | Yes | |
LastDmgTarget | unit | Yes | |
LastDmgValue | real | Yes | |
LastDmgWasSpell | boolean | Yes | |
LeaklessGroup | group | No | |
Left_Right_FusionTimer | timer | No | |
LethalDamageEvent | real | No | |
LethalDamageHP | real | No | |
Lifes | integer | No | 20 |
LifesLeaderboard | leaderboard | No | |
Loc_ofwaterPushUnit | location | No | |
LoopInt | integer | No | |
ManaARCANE_Left | real | No | |
ManaARCANE_Left_RightTrue | real | No | |
ManaARCANE_LeftRight | real | No | |
ManaARCANE_Right | real | No | |
ManaARCANE_Right_LeftTrue | real | No | |
ManaAVATAR_Left | real | No | |
ManaAVATAR_Left_RigthTrue | real | No | |
ManaAVATAR_Right | real | No | |
ManaAVATAR_Right_LeftTrue | real | No | |
ManaAVATARightLeft | real | No | |
ManaFIRE_Left | real | No | |
ManaFIRE_Left_RightTrue | real | No | |
ManaFIRE_LeftRight | real | No | |
ManaFIRE_Right | real | No | |
ManaFIRE_Right_LeftTrue | real | No | |
ManaICE_Left | real | No | |
ManaICE_Left_RightTrue | real | No | |
ManaICE_LeftRight | real | No | |
ManaICE_Right | real | No | |
ManaICE_Right_LeftTrue | real | No | |
ManaRegainINteger | integer | No | |
ManaRegainValue | real | No | |
ManaWATER_Left | real | No | |
ManaWATER_Left_RightTrue | real | No | |
ManaWATER_LeftRight | real | No | |
ManaWATER_Right | real | No | |
ManaWATER_Right_LeftTrue | real | No | |
MessageTimer | timer | No | |
Missile__Acceleration | real | No | |
Missile__Angle | real | No | |
Missile__Arc | real | No | |
Missile__Collision | real | No | |
Missile__Curve | real | No | |
Missile__Damage | real | No | |
Missile__Data | integer | No | |
Missile__DestructableHit | destructable | No | |
Missile__Distance | real | No | |
Missile__Dummy | unit | No | |
Missile__DummyTypeId | unitcode | No | |
Missile__EventId | integer | No | |
Missile__EventIndex | integer | No | |
Missile__FlyTime | real | No | |
Missile__Height | real | No | |
Missile__Impact | location | No | |
Missile__ImpactZ | real | No | |
Missile__Index | integer | No | |
Missile__Model | string | No | |
Missile__OnCollideDestructable | trigger | No | |
Missile__OnCollideUnit | trigger | No | |
Missile__OnFinish | trigger | No | |
Missile__OnPeriodic | trigger | No | |
Missile__OnRemove | trigger | No | |
Missile__Open | real | No | |
Missile__Origin | location | No | |
Missile__OriginZ | real | No | |
Missile__Owner | player | No | |
Missile__Recycle | boolean | No | |
Missile__Scale | real | No | |
Missile__Source | unit | No | |
Missile__Speed | real | No | |
Missile__Target | unit | No | |
Missile__TempLoc | location | No | |
Missile__Turn | real | No | |
Missile__UnitHit | unit | No | |
Missile__WantDestroy | boolean | No | |
Missile_A_Z | real | Yes | |
Missile_AB_Angle | real | Yes | |
Missile_AB_Distance | real | Yes | |
Missile_AB_Pitch | real | Yes | |
Missile_AB_Square | real | Yes | |
Missile_AB_Traveled | real | Yes | |
Missile_Acceleration | real | Yes | |
Missile_Angle | real | Yes | |
Missile_Arc | real | Yes | |
Missile_B_Z | real | Yes | |
Missile_Collision | real | Yes | |
Missile_Curve | real | Yes | |
Missile_CurveX | real | Yes | |
Missile_CurveY | real | Yes | |
Missile_Damage | real | Yes | |
Missile_Data | integer | Yes | |
Missile_Distance | real | Yes | |
Missile_Dummy | unit | Yes | |
Missile_Effect | effect | Yes | |
Missile_FlyTime | real | Yes | |
Missile_Height | real | Yes | |
Missile_ImpactX | real | Yes | |
Missile_ImpactY | real | Yes | |
Missile_ImpactZ | real | Yes | |
Missile_Model | string | Yes | |
Missile_OnDest | trigger | Yes | |
Missile_OnFinish | trigger | Yes | |
Missile_OnPeriodic | trigger | Yes | |
Missile_OnRemove | trigger | Yes | |
Missile_OnUnit | trigger | Yes | |
Missile_Open | real | Yes | |
Missile_OriginX | real | Yes | |
Missile_OriginY | real | Yes | |
Missile_OriginZ | real | Yes | |
Missile_Owner | player | Yes | |
Missile_PosX | real | Yes | |
Missile_PosY | real | Yes | |
Missile_PosZ | real | Yes | |
Missile_PrevX | real | Yes | |
Missile_PrevY | real | Yes | |
Missile_Recycle | boolean | Yes | |
Missile_Scale | real | Yes | |
Missile_Source | unit | Yes | |
Missile_Speed | real | Yes | |
Missile_Target | unit | Yes | |
Missile_Temploc2 | location | No | |
Missile_TerrainZ | real | Yes | |
Missile_Turn | real | Yes | |
Missile_WantDestroy | boolean | Yes | |
MissileAllocated | boolean | Yes | |
MissileCore | trigger | No | |
MissileDummyCount | integer | No | |
MissileDummyStack | unit | Yes | |
MissileDummyTime | integer | Yes | |
MissileDummyTimer | timer | No | |
MissileGroup | group | No | |
MissileHash | hashtable | No | |
MissileLaunched | boolean | Yes | |
MissileLocZ | location | No | |
MissileMaxX | integer | No | |
MissileMaxY | integer | No | |
MissileMinX | integer | No | |
MissileMinY | integer | No | |
MissileNextNode | integer | Yes | |
MissileNodes | integer | No | |
MissilePrevNode | integer | Yes | |
MissileRect | rect | No | |
MissileRecycler | integer | Yes | |
MissileTimer | timer | No | |
Mouse_Cursor_Position_P1 | location | No | |
MouseMoving | boolean | No | |
MouseX | real | Yes | |
MOUSEX | real | No | |
MOUSEY | real | No | |
MouseY | real | Yes | |
MuddedPaesant | unit | Yes | |
NextDamageOverride | boolean | No | |
NextDamageType | integer | No | |
PaesantBaseSpeed | real | No | |
PaesantMApUnitGroup | group | No | |
PaesantsAlive | integer | No | |
PotionEffectString | string | Yes | |
PotionSPlashPOint | location | Yes | |
PotionTimer | timer | No | |
PrgoressBarAnimSpeed | real | No | |
PRgressBarEffect | effect | No | |
ProgressBarUnit | unit | No | |
ProgressBarValuse | integer | No | |
Puntoesclativo | effect | Yes | |
Radians_QuarterPi | real | No | |
Radians_QuarterTurn | real | No | |
Radians_Turn | real | No | |
RANGE_ARCANE_LEFT | real | No | |
RANGE_ARCANE_LeftRight | real | No | |
RANGE_ARCANE_RIGHT | real | No | |
RANGE_AVATAR_LEFT | real | No | |
RANGE_AVATAR_LeftRight | real | No | |
RANGE_FIRE_LEFT | real | No | |
RANGE_FIRE_LEFT_RighTrue | real | No | |
RANGE_FIRE_LeftRight | real | No | |
RANGE_FIRE_RIGHT | real | No | |
RANGE_ICE_LEFT | real | No | |
RANGE_ICE_LeftRight | real | No | |
RANGE_ICE_RIGHT | real | No | |
RANGE_WATER_LEFT | real | No | |
Red_arrow_SE | effect | No | |
RED_Mouse_Left_Down | boolean | No | |
RED_Mouse_LeftAndRight_down | boolean | No | |
RED_Mouse_Middle_Down | boolean | No | |
RED_Mouse_Right_Down | boolean | No | |
RedArrowAimingON | boolean | No | |
ReducedDamageThreshold | real | No | |
SelectionImagePreview | image | No | |
ServantUNDEAD | unit | No | |
ShowwaveArrowunit | unit | No | |
SleepEffect | effect | No | |
SpellDamageAbility | abilcode | No | |
StatueLiving | unit | No | |
StaueHintTimer | timer | No | |
Stunnter | unit | No | |
TargetPoint | location | No | |
Tauren_Shockwave | boolean | Yes | |
Tauren_WarStomp | boolean | Yes | |
Teleport_unit_OUT | unit | No | |
Teleport_Unit_OUT_Preview | unit | No | |
Teleport_Unit_Select_Preview | unit | No | |
TeleportSelectionPreviewEffect | effect | No | |
Teleportunitprev_X | real | No | |
Teleportunitprev_Y | real | No | |
Temp_dummy_unit | unit | No | |
Temp_Group | group | No | |
Temp_Point_A | location | No | |
Temp_Spawn_point | location | No | |
TempEffect | effect | No | |
TempoperVincere | timer | No | |
TempReal | real | No | |
TempX | real | No | |
TempY | real | No | |
TestAlpha | integer | No | 255 |
timertime | timer | No | |
TimmyString | string | Yes | |
TimmyTextFloat | texttag | No | |
TimmyTimer | timer | No | |
TowerTest | timer | No | |
TrainerArch | unit | No | |
TrainerArchTimesHitted | integer | No | |
TutoArcVault | unit | No | |
TutoEndButton | unit | No | |
TutoEndTimer | timer | No | |
TutoString | string | No | |
TutoTimerWindow | timerdialog | No | |
UDex | integer | No | |
UDexGen | integer | No | |
UDexNext | integer | Yes | |
UDexPrev | integer | Yes | |
UDexRecycle | integer | No | |
UDexUnits | unit | Yes | |
UDexWasted | integer | No | |
UMovNext | integer | Yes | |
UMovPrev | integer | Yes | |
UnitDamageRegistered | boolean | Yes | |
UnitIndexerEnabled | boolean | No | |
UnitIndexEvent | real | No | |
UnitMovementInterval | real | No | |
UnitMoving | boolean | Yes | |
UnitMovingEvent | real | No | |
UnitMovingX | real | Yes | |
UnitMovingY | real | Yes | |
unitsentered | integer | No | |
unlmitedpower | boolean | No | |
unlmitedpower_Copy | boolean | No | |
Visibilitymoditro | fogmodifier | No | |
WATER_Damage_Left | real | No | |
WATER_Damage_LeftRight | real | No | |
WATER_Damage_Right | real | No | |
WaterChargingEffect | effect | No | |
WaterEle | unit | No | |
WaterStunner | unit | No | |
WaterUnitGroup | group | No | |
WaterUnitMoving | unit | No | |
WaterWave | boolean | No | |
WaveNumber | integer | No | 0 |
WavenumbertoREAL | real | No | |
WaveString | string | No | Wave |
WaveTimeoutTimer | timer | No | |
WaveTimeoutWindow | timerdialog | No | |
WaveTimer | timer | No | |
WaveTimerFinal | timer | No | |
WaveTimerWindow | timerdialog | No | |
WaveUnitGroup | group | No | |
WEAPON_TYPE_AM_CHOP | integer | No | |
WEAPON_TYPE_CH_SLICE | integer | No | |
WEAPON_TYPE_CL_SLICE | integer | No | |
WEAPON_TYPE_CM_SLICE | integer | No | |
WEAPON_TYPE_MH_BASH | integer | No | |
WEAPON_TYPE_MH_CHOP | integer | No | |
WEAPON_TYPE_MH_SLICE | integer | No | |
WEAPON_TYPE_MH_STAB | integer | No | |
WEAPON_TYPE_ML_CHOP | integer | No | |
WEAPON_TYPE_ML_SLICE | integer | No | |
WEAPON_TYPE_MM_BASH | integer | No | |
WEAPON_TYPE_MM_CHOP | integer | No | |
WEAPON_TYPE_MM_SLICE | integer | No | |
WEAPON_TYPE_MM_STAB | integer | No | |
WEAPON_TYPE_NONE | integer | No | |
WEAPON_TYPE_RH_BASH | integer | No | |
WEAPON_TYPE_WH_BASH | integer | No | |
WEAPON_TYPE_WH_SLICE | integer | No | |
WEAPON_TYPE_WL_BASH | integer | No | |
WEAPON_TYPE_WL_SLICE | integer | No | |
WEAPON_TYPE_WL_STAB | integer | No | |
WEAPON_TYPE_WM_BASH | integer | No | |
WEAPON_TYPE_WM_SLICE | integer | No | |
WEAPON_TYPE_WM_STAB | integer | No | |
WeaponTypeDebugStr | string | Yes | |
X_ofwaterPushUnit | real | No | |
X_ofwaterPushUnit_array | real | Yes | |
Y_ofwaterPushUnit | real | No | |
Y_ofwaterPushUnit_array | real | Yes | |
Z_loc_P1 | real | No |
function UpdateBar takes nothing returns nothing
call BlzFrameSetValue(BlzGetFrameByName("MyBarEx",0), GetUnitManaPercent(udg_ArchmageSelectable))
endfunction
function MyBarCreate takes nothing returns nothing
local framehandle bar = BlzCreateSimpleFrame("MyBarEx", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0)
call BlzFrameSetAbsPoint(bar, FRAMEPOINT_CENTER, 0.09, 0.19) // pos the bar
call BlzFrameSetSize(bar, 0.27, 0.04) //change the size of bar
call BlzFrameSetTexture(bar, "Replaceabletextures\\Teamcolor\\Teamcolor01.blp", 0, true) //color blue for bar
call BlzFrameSetText(BlzGetFrameByName("MyBarExText",0), "Mana") //change text for the Bars child named MyBarExText.
endfunction
//===========================================================================
function InitTrig_MyBar takes nothing returns nothing
local trigger trig = CreateTrigger()
set gg_trg_MyBar = CreateTrigger()
call TriggerRegisterTimerEventSingle( gg_trg_MyBar, 0.00 )
call TriggerAddAction( gg_trg_MyBar, function MyBarCreate )
call BlzLoadTOCFile("war3mapimported\\mybar.toc")
call TriggerAddAction(trig, function UpdateBar)
endfunction
//===========================================================================
// Damage Engine lets you detect, amplify, block or nullify damage. It even
// lets you detect if the damage was physical or from a spell. Just reference
// DamageEventAmount/Source/Target or the boolean IsDamageSpell, to get the
// necessary damage event data.
//
// - Detect damage (after it's been dealt to the unit): use the event "DamageEvent Equal to 1.00"
// - To change damage before it's dealt: use the event "DamageModifierEvent Equal to 1.00"
// - Detect spell damage: use the condition "IsDamageSpell Equal to True"
// - Detect zero-damage: use the event "DamageEvent Equal to 2.00" (an AfterDamageEvent will not fire for this)
//
// You can specify the DamageEventType before dealing triggered damage:
// - Set NextDamageType = DamageTypeWhatever
// - Unit - Cause...
//
// You can modify the DamageEventAmount and the DamageEventType from a "DamageModifierEvent Equal to 1.00" trigger.
// - If the amount is modified to negative, it will count as a heal.
// - If the amount is set to 0, no damage will be dealt.
//
// If you need to reference the pre-armor "pure" damage amount, use "DamageEventPureAmt"
// If you need to reference the original in-game damage, use the variable "DamageEventPrevAmt".
//
//===========================================================================
library DamageEngine initializer Init
globals
private boolean started = false
private boolean paused = false
private integer recursion = -1
private boolean recursive = false
private boolean clearable = false
private boolean purge = false
private code cleaner = null
private timer ticker = CreateTimer()
private trigger trig = CreateTrigger()
private trigger otrg = CreateTrigger()
private real spiritLinkValue = 0.00
private integer spiritLinkType = 0
private boolean spiritLinkCode = false
private unit array lastSource
private unit array lastTarget
private real array lastAmount
private attacktype array lastAttackT
private damagetype array lastDamageT
private weapontype array lastWeaponT
private trigger array lastTrig
private integer array lastType
endglobals
//GUI Vars:
/*
trigger udg_DamageEventTrigger //Different functionality from before in 5.1
boolean udg_DamageEventOverride
boolean udg_NextDamageType
boolean udg_DamageEventType
boolean udg_IsDamageCode //New in 5.1 as per request from chopinski
boolean udg_IsDamageSpell
boolean udg_IsDamageMelee //New in 5.0
boolean udg_IsDamageRanged //New in 5.0
unit udg_DamageEventSource
unit udg_DamageEventTarget
real udg_AOEDamageEvent
integer udg_DamageEventAOE
group udg_DamageEventAOEGroup
unit udg_AOEDamageSource //New in 5.0
integer udg_DamageEventLevel
unit udg_EnhancedDamageTarget
real udg_DamageEvent
real udg_DamageModifierEvent
real udg_LethalDamageEvent //New in 5.0
real udg_DamageEventAmount
real udg_DamageEventPrevAmt
real udg_LethalDamageHP //New in 5.0
integer udg_DamageEventAttackT //New in 5.0
integer udg_DamageEventDamageT //New in 5.0
integer udg_DamageEventWeaponT //New in 5.0
*/
private function Error takes nothing returns nothing
local string s = "WARNING: Recursion error when dealing damage! Prior to dealing damage from within a DamageEvent response trigger, do this:\n"
set s = s + "Set DamageEventTrigger = (This Trigger)\n"
set s = s + "Unit - Cause <Source> to damage <Target>...\n\n"
set s = s + "Alternatively, just use the UNKNOWN damage type. It will skip recursive damage on its own without needing the \"Set\" line:/n"
set s = s + "Unit - Cause <Source> to damage <Target>, dealing <Amount> damage of attack type <Attack Type> and damage type Unknown"
call ClearTextMessages()
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.00, 0.00, 999.00, s)
endfunction
//"Classic" damage event is now only used for getting the reduced damage amount and applying shields and lethal prevention.
private function DoDamageEvent takes nothing returns nothing
local boolean rec = recursive
set udg_DamageModifierEvent = 0.00
set udg_DamageModifierEvent = 4.00 //This event is used for custom shields which have a limited hit point value
set udg_LethalDamageHP = GetWidgetLife(udg_DamageEventTarget) - udg_DamageEventAmount
if udg_LethalDamageHP <= 0.405 then
set udg_LethalDamageEvent = 0.00 //New - added 10 May 2019 to detect and potentially prevent lethal damage. Instead of
set udg_LethalDamageEvent = 1.00 //modifying the damage, you need to modify LethalDamageHP instead (the final HP of the unit).
set udg_DamageEventAmount = GetWidgetLife(udg_DamageEventTarget) - udg_LethalDamageHP
if udg_DamageEventType < 0 and udg_LethalDamageHP <= 0.405 then
call SetUnitExploded(udg_DamageEventTarget, true) //Explosive damage types should blow up the target.
endif
endif
set recursive = rec
endfunction
private function WrapUpEvent takes nothing returns nothing
local boolean rec = recursive
if udg_DamageEventDamageT > 0 then //Ignore DAMAGE_TYPE_UNKNOWN
set recursive = true
if udg_DamageEventAmount < 0.00 then
call SetWidgetLife(udg_DamageEventTarget, GetWidgetLife(udg_DamageEventTarget) - udg_DamageEventAmount)
endif
set udg_DamageEvent = 0.00
set udg_DamageEvent = 1.00 //AfterDamageEvent was removed as it is no longer required.
set recursive = rec
endif
endfunction
private function ClearDamageEvent takes nothing returns nothing
local integer i = -1
if not IsTriggerEnabled(trig) then
call EnableTrigger(trig)
endif
if clearable then
set clearable = false
if not purge and recursion > -1 then
set purge = true
call ForForce(bj_FORCE_PLAYER[0], cleaner)
set purge = false
set recursive = false
endif
endif
endfunction
private function OnAOEEnd takes nothing returns nothing
if udg_DamageEventAOE > 1 then
set udg_AOEDamageEvent = 0.00
set udg_AOEDamageEvent = 1.00
set udg_DamageEventAOE = 1
endif
set udg_DamageEventLevel = 1
set udg_EnhancedDamageTarget = null
set udg_AOEDamageSource = null
call GroupClear(udg_DamageEventAOEGroup)
endfunction
private function OnExpire takes nothing returns nothing
call ClearDamageEvent() //Check for any lingering damage
set started = false //The timer has expired. Flag off to allow it to be restarted when needed.
call OnAOEEnd() //Reset things so they don't perpetuate for AoE/Level target detection
endfunction
private function SetVars takes unit src, unit tgt, real amt, attacktype at, damagetype dt, weapontype wt, integer ph returns boolean
local integer i = recursion + 1
local boolean rec = recursive
if ph < 2 and udg_NextDamageType == 0 and (udg_DamageEventTrigger != null or rec) then
set udg_NextDamageType = udg_DamageTypeCode
endif
if rec and ph == 1 then
set recursion = i
if i < 16 and (dt == null or udg_DamageEventTrigger != null or not purge) then //when 16 events are run recursively from one damage instance, it's a safe bet that something has gone wrong.
//If "purge" is True and this is running, the damage is trying to fire off of an already-recursive function and didn't use the safety trigger.
//This is pretty much guaranteed to be unwanted behavior.
set lastAmount[i] = amt
if amt != 0.00 then
//Store recursive damage into a queue from index i (0-15)
//This damage will be fired after the current damage instance has wrapped up its events.
//This damage can only be caused by triggers.
set lastSource[i] = src
set lastTarget[i] = tgt
set lastAttackT[i] = at
set lastDamageT[i] = dt
set lastWeaponT[i] = wt
if udg_NextDamageType != 0 then
set lastTrig[i] = udg_DamageEventTrigger
set lastType[i] = udg_NextDamageType
endif
endif
else
//Delete or comment-out the next lines to disable the in-game recursion crash warnings
call Error()
endif
set udg_NextDamageType = 0
set udg_DamageEventTrigger = null
return false
endif
if ph == 1 then
//Added 25 July 2017 to detect AOE damage or multiple single-target damage
if started then
if src != udg_AOEDamageSource then //Source has damaged more than once
call OnAOEEnd() //New damage source - unflag everything
set udg_AOEDamageSource = src
elseif tgt == udg_EnhancedDamageTarget then
set udg_DamageEventLevel = udg_DamageEventLevel + 1 //The number of times the same unit was hit.
elseif not IsUnitInGroup(tgt, udg_DamageEventAOEGroup) then
set udg_DamageEventAOE = udg_DamageEventAOE + 1 //Multiple targets hit by this source - flag as AOE
endif
if dt == DAMAGE_TYPE_SPIRIT_LINK and udg_DamageEventAOE + udg_DamageEventLevel == 3 then
set spiritLinkValue = udg_DamageEventPrevAmt//Store any potential pure damage spirit link amount.
set spiritLinkType = udg_DamageEventType //also store the damage type.
set spiritLinkCode = udg_IsDamageCode
endif
else
set started = true
set udg_AOEDamageSource = src
set udg_EnhancedDamageTarget = tgt
call TimerStart(ticker, 0.00, false, function OnExpire)
endif
call GroupAddUnit(udg_DamageEventAOEGroup, tgt)
endif
if ph == 2 then
set udg_DamageEventPrevAmt = spiritLinkValue
set udg_DamageEventType = spiritLinkType
set udg_IsDamageCode = spiritLinkCode
else
set udg_DamageEventPrevAmt = amt
set udg_DamageEventType = udg_NextDamageType
if udg_NextDamageType != 0 then
set udg_DamageEventType = udg_NextDamageType
set udg_NextDamageType = 0
set udg_IsDamageCode = true //New in 5.1 - requested by chopinski to allow user to detect Code damage
set udg_DamageEventTrigger = null
endif
set udg_DamageEventOverride = dt == null or udg_DamageEventType*udg_DamageEventType == 4 //Got rid of NextDamageOverride in 5.1 for simplicity
//call BJDebugMsg(GetUnitName(tgt))
endif
set udg_DamageEventSource = src
set udg_DamageEventTarget = tgt
set udg_DamageEventAmount = amt
set udg_DamageEventAttackT = GetHandleId(at)
set udg_DamageEventDamageT = GetHandleId(dt)
set udg_DamageEventWeaponT = GetHandleId(wt)
//Set Melee and Ranged detection.
set udg_IsDamageMelee = false
set udg_IsDamageRanged = false
set udg_IsDamageSpell = at == null //In Patch 1.31, one can just check the attack type to find out if it's a spell.
if dt == DAMAGE_TYPE_NORMAL and not udg_IsDamageSpell and not udg_IsDamageCode then //This damage type is the only one that can get reduced by armor.
set udg_IsDamageMelee = IsUnitType(src, UNIT_TYPE_MELEE_ATTACKER)
set udg_IsDamageRanged = IsUnitType(src, UNIT_TYPE_RANGED_ATTACKER)
if udg_IsDamageMelee and udg_IsDamageRanged then
set udg_IsDamageMelee = wt != null // Melee units play a sound when damaging
set udg_IsDamageRanged = not udg_IsDamageMelee // In the case where a unit is both ranged and melee, the ranged attack plays no sound.
endif // The Huntress has a melee sound for her ranged projectile, however it is only an issue
endif //if she also had a melee attack, because by default she is only UNIT_TYPE_RANGED_ATTACKER.
set recursive = true
if ph == 2 then
call DoDamageEvent()
elseif not udg_DamageEventOverride then
//Ignores event on various debuffs like Faerie Fire - alternatively,
//the user can exploit UNKNOWN damage type to avoid damage detection.
set udg_DamageModifierEvent = 0.00
set udg_DamageModifierEvent = 1.00 //I recommend using this for changing damage types or for when you need to do things that should override subsequent damage modification.
set udg_DamageEventOverride = udg_DamageEventOverride or udg_DamageEventType*udg_DamageEventType == 4
if not udg_DamageEventOverride then
set udg_DamageModifierEvent = 2.00 //This should involve damage calculation based on multiplication/percentages.
set udg_DamageModifierEvent = 3.00 //This should just be addition or subtraction at this point.
endif
endif
set recursive = rec
if ph < 2 and udg_DamageEventAmount <= 0.00 then //The next event doesn't run if this damage is zero or less than zero.
call WrapUpEvent()
set clearable = true
endif
return true
endfunction
private function OnPreDamage takes nothing returns boolean
call ClearDamageEvent()
//Load the event responses into the Pre-Damage Modification trigger.
if SetVars(GetEventDamageSource(), BlzGetEventDamageTarget(), GetEventDamage(), BlzGetEventAttackType(), BlzGetEventDamageType(), BlzGetEventWeaponType(), 1) then
//All events have run and the damage amount is finalized.
call BlzSetEventAttackType(ConvertAttackType(udg_DamageEventAttackT))
call BlzSetEventDamageType(ConvertDamageType(udg_DamageEventDamageT))
call BlzSetEventWeaponType(ConvertWeaponType(udg_DamageEventWeaponT))
if udg_DamageEventAmount > 0.00 then
call BlzSetEventDamage(udg_DamageEventAmount)
return false
//Healing causes issues here as the negative damage is not always counted as a heal (for example with physical damage).
//I therefore run a separate heal process from the "After Damage" moment which works for all circumstances.
endif
endif
call BlzSetEventDamage(0.00) //queue the damage instance instead of letting it run recursively
return false
endfunction
private function UDTX takes unit src, unit tgt, real amt, boolean a, boolean r, attacktype at, damagetype dt, weapontype wt, integer ph returns boolean
if SetVars(src, tgt, amt, at, dt, wt, ph) then
call DisableTrigger(trig)
call UnitDamageTarget(udg_DamageEventSource, udg_DamageEventTarget, udg_DamageEventAmount, a, r, ConvertAttackType(udg_DamageEventAttackT), ConvertDamageType(udg_DamageEventDamageT), ConvertWeaponType(udg_DamageEventWeaponT))
call ClearDamageEvent()
return true
endif
return false
endfunction
private function DoCleanup takes nothing returns nothing
local integer i = -1
loop
exitwhen i >= recursion
set i = i + 1 //Need to loop bottom to top to make sure damage order is preserved.
if lastAmount[i] != 0.00 then
set udg_NextDamageType = lastType[i]
if lastTrig[i] != null then
call DisableTrigger(lastTrig[i])//Since the damage is run sequentially now, rather than recursively, the system needs to disable the user's trigger for them.
endif
call UDTX(lastSource[i], lastTarget[i], lastAmount[i], true, false, lastAttackT[i], lastDamageT[i], lastWeaponT[i], -1)
endif
endloop
loop
exitwhen i <= -1
if lastTrig[i] != null then
call EnableTrigger(lastTrig[i]) //Only re-enable recursive triggers AFTER all damage is dealt.
endif
set i = i - 1
endloop
set recursion = -1 //Can only be set after all the damage has successfully ended.
endfunction
//The traditional on-damage response, where armor reduction has already been factored in.
private function OnDamage takes nothing returns boolean
local real r = GetEventDamage()
local damagetype dt = BlzGetEventDamageType()
if not IsTriggerEnabled(trig) then
call EnableTrigger(trig) //With UnitDamageTargetEx this trigger gets disabled.
endif
if recursive then
call BlzSetEventDamage(0.00)
return false
endif
if udg_DamageEventDamageT == udg_DAMAGE_TYPE_SPIRIT_LINK and dt != DAMAGE_TYPE_SPIRIT_LINK then
//Unfortunately, this event fires out of sequence from the other damage events, so I have to re-generate some stuff here.
call SetVars(udg_DamageEventSource, BlzGetEventDamageTarget(), GetEventDamage(), BlzGetEventAttackType(), dt, BlzGetEventWeaponType(), 2)
else
if not udg_DamageEventOverride then //DamageEventAmount remains unmodified by in-game damage processing for DamageTypePure.
set udg_DamageEventAmount = r //Damage may have been further adjusted (ie. unit armor or armor type reduction)
endif
if udg_DamageEventAmount > 0.00 then
call DoDamageEvent()
endif
endif
call BlzSetEventDamage(udg_DamageEventAmount) //Apply the final damage amount.
call WrapUpEvent()
set clearable = true
return false
endfunction
//===========================================================================
private function Init takes nothing returns nothing
call TriggerRegisterAnyUnitEventBJ(otrg, EVENT_PLAYER_UNIT_DAMAGED) //Thanks to this I no longer have to have 1 event for all units in the map.
call TriggerAddCondition(otrg, Filter(function OnDamage))
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_DAMAGING) //The new 1.31 event which fires before damage.
call TriggerAddCondition(trig, Filter(function OnPreDamage))
set cleaner = function DoCleanup
endfunction
public function DebugStr takes nothing returns nothing
set udg_AttackTypeDebugStr[0] = "SPELLS"
set udg_AttackTypeDebugStr[1] = "NORMAL"
set udg_AttackTypeDebugStr[2] = "PIERCE"
set udg_AttackTypeDebugStr[3] = "SIEGE"
set udg_AttackTypeDebugStr[4] = "MAGIC"
set udg_AttackTypeDebugStr[5] = "CHAOS"
set udg_AttackTypeDebugStr[6] = "HERO"
set udg_DamageTypeDebugStr[0] = "UNKNOWN"
set udg_DamageTypeDebugStr[4] = "NORMAL"
set udg_DamageTypeDebugStr[5] = "ENHANCED"
set udg_DamageTypeDebugStr[8] = "FIRE"
set udg_DamageTypeDebugStr[9] = "COLD"
set udg_DamageTypeDebugStr[10] = "LIGHTNING"
set udg_DamageTypeDebugStr[11] = "POISON"
set udg_DamageTypeDebugStr[12] = "DISEASE"
set udg_DamageTypeDebugStr[13] = "DIVINE"
set udg_DamageTypeDebugStr[14] = "MAGIC"
set udg_DamageTypeDebugStr[15] = "SONIC"
set udg_DamageTypeDebugStr[16] = "ACID"
set udg_DamageTypeDebugStr[17] = "FORCE"
set udg_DamageTypeDebugStr[18] = "DEATH"
set udg_DamageTypeDebugStr[19] = "MIND"
set udg_DamageTypeDebugStr[20] = "PLANT"
set udg_DamageTypeDebugStr[21] = "DEFENSIVE"
set udg_DamageTypeDebugStr[22] = "DEMOLITION"
set udg_DamageTypeDebugStr[23] = "SLOW_POISON"
set udg_DamageTypeDebugStr[24] = "SPIRIT_LINK"
set udg_DamageTypeDebugStr[25] = "SHADOW_STRIKE"
set udg_DamageTypeDebugStr[26] = "UNIVERSAL"
set udg_WeaponTypeDebugStr[0] = "NONE"
set udg_WeaponTypeDebugStr[1] = "METAL_LIGHT_CHOP"
set udg_WeaponTypeDebugStr[2] = "METAL_MEDIUM_CHOP"
set udg_WeaponTypeDebugStr[3] = "METAL_HEAVY_CHOP"
set udg_WeaponTypeDebugStr[4] = "METAL_LIGHT_SLICE"
set udg_WeaponTypeDebugStr[5] = "METAL_MEDIUM_SLICE"
set udg_WeaponTypeDebugStr[6] = "METAL_HEAVY_SLICE"
set udg_WeaponTypeDebugStr[7] = "METAL_MEDIUM_BASH"
set udg_WeaponTypeDebugStr[8] = "METAL_HEAVY_BASH"
set udg_WeaponTypeDebugStr[9] = "METAL_MEDIUM_STAB"
set udg_WeaponTypeDebugStr[10] = "METAL_HEAVY_STAB"
set udg_WeaponTypeDebugStr[11] = "WOOD_LIGHT_SLICE"
set udg_WeaponTypeDebugStr[12] = "WOOD_MEDIUM_SLICE"
set udg_WeaponTypeDebugStr[13] = "WOOD_HEAVY_SLICE"
set udg_WeaponTypeDebugStr[14] = "WOOD_LIGHT_BASH"
set udg_WeaponTypeDebugStr[15] = "WOOD_MEDIUM_BASH"
set udg_WeaponTypeDebugStr[16] = "WOOD_HEAVY_BASH"
set udg_WeaponTypeDebugStr[17] = "WOOD_LIGHT_STAB"
set udg_WeaponTypeDebugStr[18] = "WOOD_MEDIUM_STAB"
set udg_WeaponTypeDebugStr[19] = "CLAW_LIGHT_SLICE"
set udg_WeaponTypeDebugStr[20] = "CLAW_MEDIUM_SLICE"
set udg_WeaponTypeDebugStr[21] = "CLAW_HEAVY_SLICE"
set udg_WeaponTypeDebugStr[22] = "AXE_MEDIUM_CHOP"
set udg_WeaponTypeDebugStr[23] = "ROCK_HEAVY_BASH"
endfunction
//New function that hacks a UDT call directly into the damage modification phase, setting some stuff automatically for the user.
function UnitDamageTargetEx takes unit src, unit tgt, real amt, boolean a, boolean r, attacktype at, damagetype dt, weapontype wt returns boolean
if udg_DamageEventTrigger == null then
set udg_DamageEventTrigger = GetTriggeringTrigger() //Directly access the user's calling trigger
endif
if udg_NextDamageType == 0 then
set udg_NextDamageType = udg_DamageTypeCode
endif
return UDTX(src, tgt, amt, a, r, at, dt, wt, 1)
endfunction
endlibrary
// Arcing Text Tag v1.0.0.3 by Maker
library FloatingTextArc
globals
private constant real SIZE_MIN = 0.018 // Minimum size of text
private constant real SIZE_BONUS = 0.012 // Text size increase
private constant real TIME_LIFE = 0.8 // How long the text lasts
private constant real TIME_FADE = 0.6 // When does the text start to fade
private constant real Z_OFFSET = 80 // Height above unit
private constant real Z_OFFSET_BON = 60 // How much extra height the text gains
private constant real VELOCITY = 4 // How fast the text move in x/y plane
private constant real ANGLE = bj_PI/2 // Movement angle of the text. Does not apply if
// ANGLE_RND is true
private constant boolean ANGLE_RND = true // Is the angle random or fixed
private timer TMR = CreateTimer()
endglobals
struct ArcingTextTag extends array
private texttag tt
private real as // angle, sin component
private real ac // angle, cos component
private real ah // arc height
private real t // time
private real x // origin x
private real y // origin y
private string s // text
private static integer array next
private static integer array prev
private static integer array rn
private static integer ic = 0 // Instance count
private static method update takes nothing returns nothing
local thistype this=next[0]
local real p
loop
set p = Sin(bj_PI*.t)
set .t = .t - 0.03125
set .x = .x + .ac
set .y = .y + .as
call SetTextTagPos(.tt, .x, .y, Z_OFFSET + Z_OFFSET_BON * p)
call SetTextTagText(.tt, .s, SIZE_MIN + SIZE_BONUS * p)
if .t <= 0 then
set .tt = null
set next[prev[this]] = next[this]
set prev[next[this]] = prev[this]
set rn[this] = rn[0]
set rn[0] = this
if next[0]==0 then
call PauseTimer(TMR)
endif
endif
set this = next[this]
exitwhen this == 0
endloop
endmethod
public static method create takes string s, unit u returns thistype
local thistype this = rn[0]
static if ANGLE_RND then
local real a = GetRandomReal(0, 2*bj_PI)
else
local real a = ANGLE
endif
if this == 0 then
set ic = ic + 1
set this = ic
else
set rn[0] = rn[this]
endif
set next[this] = 0
set prev[this] = prev[0]
set next[prev[0]] = this
set prev[0] = this
set .s = s
set .x = GetUnitX(u)
set .y = GetUnitY(u)
set .t = TIME_LIFE
set .as = Sin(a)*VELOCITY
set .ac = Cos(a)*VELOCITY
set .ah = 0.
if IsUnitVisible(u, GetLocalPlayer()) then
set .tt = CreateTextTag()
call SetTextTagPermanent(.tt, false)
call SetTextTagLifespan(.tt, TIME_LIFE)
call SetTextTagFadepoint(.tt, TIME_FADE)
call SetTextTagText(.tt, s, SIZE_MIN)
call SetTextTagPos(.tt, .x, .y, Z_OFFSET)
endif
if prev[this] == 0 then
call TimerStart(TMR, 0.03125, true, function thistype.update)
endif
return this
endmethod
endstruct
endlibrary
//TESH.scrollpos=205
//TESH.alwaysfold=0
function K2DItemCheckXY takes real x, real y returns boolean
call SetItemPosition(udg_K2DItem, x, y)
return GetWidgetX(udg_K2DItem) == x and GetWidgetY(udg_K2DItem) == y
endfunction
function K2DItemCheckAxis takes real x, real y returns boolean
local real x2 = x*udg_K2DRadius[udg_UDex]
local real y2 = y*udg_K2DRadius[udg_UDex]
set x = udg_K2DX + x2
set y = udg_K2DY + y2
if K2DItemCheckXY(x, y) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) then
set x = udg_K2DX - x2
set y = udg_K2DY - y2
return K2DItemCheckXY(x, y) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
endif
return false
endfunction
function K2DItemCheck takes nothing returns boolean
local boolean result = K2DItemCheckXY(udg_K2DX, udg_K2DY)
//Only perform additional pathing checks if the unit has a larger collision.
if result and udg_Knockback2DRobustPathing > 0 and udg_K2DRadius[udg_UDex] > 0 then
//Check horizontal axis of unit to make sure nothing is going to collide
set result = K2DItemCheckAxis(udg_K2DCosH[udg_UDex], udg_K2DSinH[udg_UDex])
//Check vertical axis of unit to ensure nothing will collide
set result = result and K2DItemCheckAxis(udg_K2DCos[udg_UDex], udg_K2DSin[udg_UDex])
if result and udg_Knockback2DRobustPathing == 2 and udg_K2DRadius[udg_UDex] > 16 then
//Check diagonal axis of unit if more thorough pathing is desired
set result = K2DItemCheckAxis(udg_K2DCosD1[udg_UDex], udg_K2DSinD1[udg_UDex])
set result = result and K2DItemCheckAxis(udg_K2DCosD2[udg_UDex], udg_K2DSinD2[udg_UDex])
endif
endif
//Reset item so it won't interfere with the map
call SetItemPosition(udg_K2DItem, udg_K2DMaxX, udg_K2DMaxY)
call SetItemVisible(udg_K2DItem, false)
return result
endfunction
function K2DItemFilter takes nothing returns boolean
//Check for visible items, temporarily hide them and add them to the filter.
if IsItemVisible(GetFilterItem()) then
call SetItemVisible(GetFilterItem(), false)
return true
endif
return false
endfunction
function K2DItemCode takes nothing returns nothing
//Perform the item-pathing check only once, then unhide those filtered items
if not udg_K2DItemsFound then
set udg_K2DItemsFound = true
set udg_K2DItemOffset = K2DItemCheck()
endif
call SetItemVisible(GetEnumItem(), true)
endfunction
function K2DKillDest takes nothing returns nothing
local real x
local real y
//Handle destruction of debris
set bj_destRandomCurrentPick = GetEnumDestructable()
if GetWidgetLife(bj_destRandomCurrentPick) > 0.405 and IssueTargetOrder(udg_K2DDebrisKiller, udg_Knockback2DTreeOrDebris, bj_destRandomCurrentPick) then
set x = GetWidgetX(bj_destRandomCurrentPick) - udg_K2DX
set y = GetWidgetY(bj_destRandomCurrentPick) - udg_K2DY
if x*x + y*y <= udg_K2DDestRadius[udg_UDex] then
call KillDestructable(bj_destRandomCurrentPick)
endif
endif
endfunction
function K2DEnumDests takes nothing returns nothing
call MoveRectTo(udg_K2DRegion, udg_K2DX, udg_K2DY)
if udg_K2DKillTrees[udg_UDex] then
call SetUnitX(udg_K2DDebrisKiller, udg_K2DX)
call SetUnitY(udg_K2DDebrisKiller, udg_K2DY)
call EnumDestructablesInRect(udg_K2DRegion, null, function K2DKillDest)
endif
endfunction
function Knockback2DCheckXY takes real x, real y returns boolean
set udg_K2DX = x + udg_K2DVelocity[udg_UDex]*udg_K2DCos[udg_UDex]
set udg_K2DY = y + udg_K2DVelocity[udg_UDex]*udg_K2DSin[udg_UDex]
if udg_K2DSimple[udg_UDex] then
//A "pull" effect or a missile system does not require complex pathing.
if udg_K2DX <= udg_K2DMaxX and udg_K2DX >= udg_K2DMinX and udg_K2DY <= udg_K2DMaxY and udg_K2DY >= udg_K2DMinY then
call K2DEnumDests()
return true
endif
return false
elseif udg_K2DFlying[udg_UDex] then
return not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_FLYABILITY)
elseif not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_WALKABILITY) then
call K2DEnumDests()
set udg_K2DItemOffset = false
call EnumItemsInRect(udg_K2DRegion, Filter(function K2DItemFilter), function K2DItemCode)
if udg_K2DItemsFound then
//If items were found, the check was already performed.
set udg_K2DItemsFound = false
else
//Otherwise, perform the check right now.
set udg_K2DItemOffset = K2DItemCheck()
endif
return udg_K2DItemOffset
endif
return udg_K2DAmphibious[udg_UDex] and not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_FLOATABILITY)
endfunction
function Knockback2DApplyAngle takes real angle returns nothing
set angle = ModuloReal(angle, udg_Radians_Turn)
set udg_K2DCos[udg_UDex] = Cos(angle)
set udg_K2DSin[udg_UDex] = Sin(angle)
set udg_K2DAngle[udg_UDex] = angle
if udg_Knockback2DRobustPathing > 0 then
set angle = ModuloReal(angle + udg_Radians_QuarterTurn, udg_Radians_Turn)
set udg_K2DCosH[udg_UDex] = Cos(angle)
set udg_K2DSinH[udg_UDex] = Sin(angle)
if udg_Knockback2DRobustPathing == 2 and udg_K2DRadius[udg_UDex] > 16 then
set angle = ModuloReal(angle + udg_Radians_QuarterPi, udg_Radians_Turn)
set udg_K2DCosD1[udg_UDex] = Cos(angle)
set udg_K2DSinD1[udg_UDex] = Sin(angle)
set angle = ModuloReal(angle + udg_Radians_QuarterTurn, udg_Radians_Turn)
set udg_K2DCosD2[udg_UDex] = Cos(angle)
set udg_K2DSinD2[udg_UDex] = Sin(angle)
endif
endif
endfunction
function Knockback2DLooper takes nothing returns nothing
local integer i = 0
local unit u
local real x
local real y
call PauseUnit(udg_K2DDebrisKiller, false)
loop
set i = udg_K2DNext[i]
exitwhen i == 0
set udg_UDex = i
set udg_K2DTimeLeft[i] = udg_K2DTimeLeft[i] - udg_K2DTimeout
set udg_K2DDistanceLeft[i] = udg_K2DDistanceLeft[i] - udg_K2DVelocity[i]
set u = udg_UDexUnits[i]
if udg_K2DTimeLeft[i] > 0.00 then
if udg_K2DTimeLeft[i] < udg_K2DHeightThreshold[i] and udg_K2DHeightThreshold[i] != 0.00 then
call SetUnitFlyHeight(u, GetUnitDefaultFlyHeight(u), GetUnitFlyHeight(u) - GetUnitDefaultFlyHeight(u)/udg_K2DHeightThreshold[i])
set udg_K2DHeightThreshold[i] = 0.00
endif
if udg_K2DPause[i] then
set x = udg_K2DLastX[i]
set y = udg_K2DLastY[i]
else
set x = GetUnitX(u)
set y = GetUnitY(u)
endif
if not Knockback2DCheckXY(x, y) then
if not udg_K2DFreeze[i] and IsTriggerEnabled(udg_K2DImpact[i]) and TriggerEvaluate(udg_K2DImpact[i]) then
call TriggerExecute(udg_K2DImpact[i])
endif
if udg_K2DBounce[i] then
call Knockback2DApplyAngle(udg_Radians_Turn - udg_K2DAngle[i])
if not Knockback2DCheckXY(x, y) then
call Knockback2DApplyAngle(udg_K2DAngle[i] + bj_PI)
if not Knockback2DCheckXY(x, y) then
call Knockback2DApplyAngle(udg_Radians_Turn - udg_K2DAngle[i])
set udg_K2DX = x
set udg_K2DY = y
endif
endif
else
set udg_K2DX = x
set udg_K2DY = y
set udg_K2DFreeze[i] = true
endif
endif
call SetUnitX(u, udg_K2DX)
call SetUnitY(u, udg_K2DY)
set udg_K2DLastX[i] = udg_K2DX
set udg_K2DLastY[i] = udg_K2DY
if udg_K2DFXModel[i] != "" then
set udg_K2DFXTimeLeft[i] = udg_K2DFXTimeLeft[i] - udg_K2DTimeout
if udg_K2DFXTimeLeft[i] <= 0.00 then
set udg_K2DFXTimeLeft[i] = udg_K2DFXRate[i]
if udg_K2DFlying[i] then
call DestroyEffect(AddSpecialEffectTarget(udg_K2DFXModel[i], u, "origin"))
else
call DestroyEffect(AddSpecialEffect(udg_K2DFXModel[i], udg_K2DX, udg_K2DY))
endif
endif
endif
if udg_K2DCollision[i] >= 0.00 then
set udg_Knockback2DSource = u
call GroupEnumUnitsInRange(bj_lastCreatedGroup, udg_K2DX, udg_K2DY, 200.00, null)
call GroupRemoveUnit(bj_lastCreatedGroup, u)
loop
set udg_Knockback2DUnit = FirstOfGroup(bj_lastCreatedGroup)
exitwhen udg_Knockback2DUnit == null
call GroupRemoveUnit(bj_lastCreatedGroup, udg_Knockback2DUnit)
if IsUnitInRange(udg_Knockback2DUnit, u, udg_K2DCollision[i]) and udg_K2DFlying[i] == IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_FLYING) and (not IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_STRUCTURE)) and not IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_DEAD) and (udg_K2DUnbiasedCollision[i] or IsUnitAlly(udg_Knockback2DUnit, GetOwningPlayer(u))) and TriggerEvaluate(gg_trg_Knockback_2D) then
set udg_Knockback2DAngle = bj_RADTODEG * Atan2(GetUnitY(udg_Knockback2DUnit) - udg_K2DY, GetUnitX(udg_Knockback2DUnit) - udg_K2DX)
set udg_Knockback2DDistance = udg_K2DDistanceLeft[i]
set udg_Knockback2DBounces = udg_K2DBounce[i]
set udg_Knockback2DCollision = udg_K2DCollision[i]
if udg_K2DHeight[i] != 0.00 then
set udg_Knockback2DHeight = GetUnitFlyHeight(u) - GetUnitDefaultFlyHeight(u)
endif
set udg_Knockback2DLoopFX = udg_K2DFXModel[i]
set udg_Knockback2DTime = udg_K2DTimeLeft[i]
set udg_Knockback2DUnbiasedCollision = udg_K2DUnbiasedCollision[i]
call TriggerExecute(gg_trg_Knockback_2D)
set udg_Knockback2DSource = u //in case of a recursive knockback
endif
endloop
endif
set udg_K2DVelocity[i] = udg_K2DVelocity[i] - udg_K2DFriction[i]
else
call TriggerExecute(gg_trg_Knockback_2D_Destroy)
endif
endloop
set u = null
//Disable dummy after the loop finishes so it doesn't interfere with the map
call PauseUnit(udg_K2DDebrisKiller, true)
endfunction
//===========================================================================
function StartKnockback2DTimer takes nothing returns nothing
call TimerStart(udg_K2DTimer, udg_K2DTimeout, true, function Knockback2DLooper)
endfunction
function InitTrig_Knockback_2D_System takes nothing returns nothing
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
//=============================================================
// Name: Missile
// Version: 1.6.1
// Description: A system for your projectile needs.
// Author: BPower
//
// Written in JASS, API designed for usage with GUI.
// Published on hiveworkshop.com
// - hiveworkshop.com/forums/spells-569/missile-gui-version-1-1-a-275718/
//=============================================================
// Before getting started make sure that you check
// the settings in trigger Missile Configurate.
//
// udg_Missile__DummyTypeId
// • Make sure you have Vexorians dummy.mdx imported.
// • Only units of this type id will be recycled.
//
//=============================================================
// Variable naming.
//=============================================================
// Variables which users shouldn't access have no underscore.
// Array variables which are available at any time have one underscore _.
// Scalar variables which are only available during events have two underscores __.
//
//=============================================================
// Missile API.
//=============================================================
// Syntax for missile creation in GUI:
// 1. Run trigger Missile Configurate <gen>
// 2. Set properties via scalar variables.
// 3. Run trigger Missile <gen>
// JASS users may call the create and launch function directly.
//
// Missile operates with custom events.
// This means that you have access to
// a missile's properties within action functions
// of the Missile trigger interface.
//
// "udg_Missile__EventId" indicates
// which event trigger has been dispatched.
//
// "udg_Missile__EventIndex" is the array index
// of the triggering missile.
//
// Avaliable events are:
//
// 1.) udg_EVENT_MISSILE_COLLIDE_UNIT
// • Runs when a missile collides with a unit.
//
// 2.) udg_EVENT_MISSILE_COLLIDE_DEST
// • Runs when a missile collides with a destructable.
//
// 3.) udg_EVENT_MISSILE_PERIODIC
// • Runs every missile timer interval.
//
// 4.) udg_EVENT_MISSILE_FINISH
// • Runs when a missile reaches its impact position.
//
// 5.) udg_EVENT_MISSILE_REMOVE
// • Runs when a missile is destroyed.
//
// 6.) udg_EVENT_MISSILE_NOTHING
// • Value of udg_Missile__EventId when accessed
// from outside a trigger action function.
//
// During every missile event you may use the
// following GUI generated variables.
// Every scalar variable has an equivalent array variable,
// which you can read and use at any time.
// For exmple: udg_Missile__Source vs. udg_Missile_Source[index]
//
// Trigger variables which fire Missile events:
//
// trigger udg_Missile__OnCollideUnit - trigger array udg_Missile_OnUnit
// trigger udg_Missile__OnCollideDestructable - trigger array udg_Missile_OnDest
// trigger udg_Missile__OnPeridoic - trigger array udg_Missile_OnPeriodic
// trigger udg_Missile__OnRemove - trigger array udg_Missile_OnRemove
// trigger udg_Missile__OnFinish - trigger array udg_Missile_OnFinish
//
// Variables which mimic a function call:
//
// location udg_Missile__Origin
// location udg_Missile__Impact
// boolean udg_Missile__WantDestroy - boolean array udg_Missile_WantDestroy
// boolean udg_Missile__Recycle - boolean array udg_Missile_Recycle
// real udg_Missile__Scale - real array udg_Missile_Scale
// real udg_Missile__FlyTime - real array udg_Missile_FlyTime ( Converts time in seconds to a vector lenght )
// real udg_Missile__Model - string array udg_Missile_Model ( Converts a string path to a special effect )
// real udg_Missile__Arc - real array udg_Missile_Arc ( Converts an arc in degree to height value )
// real udg_Missile__Curve - real array udg_Missile_Curve ( Converts a curve in degree to an open value )
//
// Variables for read-only:
//
// integer udg_Missile__EventId
// integer udg_Missile__EventIndex
// unit udg_Missile__Dummy - unit array udg_Missile_Dummy
// real udg_Missile__Angle - real array udg_Missile_Angle ( In radians )
// real udg_Missile__Distance - real array udg_Missile_Distance ( Total distance traveled )
//
// Variables for read and set.
//
// unit udg_Missile__Source - unit array udg_Missile_Source
// unit udg_Missile__Target - unit array udg_Missile_Target ( Enables homing behaviour towards a target unit )
// player udg_Missile__Owner - unit array udg_Missile_Owner ( Pseudo-owner for better onCollide evaluation )
// real udg_Missile__ImpactZ - real array udg_Missile_ImpactZ
// real udg_Missile__OriginZ - real array udg_Missile_OriginZ
// real udg_Missile__Damage - real array udg_Missile_Damage
// real udg_Missile__Collision - real array udg_Missile_Collision
// real udg_Missile__Speed - real array udg_Missile_Speed
// real udg_Missile__Acceleration - real array udg_Missile_Acceleration
// real udg_Missile__Height - real array udg_Missile_Height ( Highest point of the parabola )
// real udg_Missile__Open - real array udg_Missile_Open
// real udg_Missile__Turn - real array udg_Missile_Turn ( Turn ratio per second )
// real udg_Missile__Data - integer array udg_Missile_Data
//
//=============================================================
// JASS user settings.
//=============================================================
// Set the timer timeout for projectile motion and trigger interface evaluation.
constant function Missile_GetTimerTimeout takes nothing returns real
return 0.031250000
endfunction
// Set the maximum widget collision radius in this map.
// By default the largest pathing is the human townhall with 196.
constant function Missile_GetMaxCollision takes nothing returns real
return 196.
endfunction
// Set the owning player of all dummy units.
// It should be a neutral player in your map.
constant function Missile_GetDummyOwner takes nothing returns player
return Player(PLAYER_NEUTRAL_PASSIVE)
endfunction
// Fictional z height for units in your map.
function Missile_GetUnitBodySize takes unit whichUnit returns real
return 100.
endfunction
// Fictional z height for destructables in your map.
function Missile_GetDestructableHeight takes destructable whichDest returns real
return GetDestructableOccluderHeight(whichDest)
endfunction
// Fictional value for the maximum effect death time in your map.
constant function Missile_GetEffectDeathTime takes nothing returns integer
return 3
endfunction
//=============================================================
// Required utility functions.
//=============================================================
// Debugging Missile.
// Change the condition from "true" to "false" or delete
// the content of this function to disable error messages.
function Missile_ErrorMessage takes boolean expr, string func, string object, integer index, string text returns nothing
local string orange = "|cffffa500"
local string blue = "|cff99b4d1"
local string next = "\n"
local string space = " "
local string str = space + next
if expr and true then
set str = str + orange + "Error in Trigger Missile|r"
set str = str + next + next + space + orange + "Function: |r" + blue + func + "|r"
set str = str + next + space + orange + "Object: |r" + blue + object + "|r"
set str = str + next + space + orange + "Index: |r" + blue + I2S(index) + "|r"
set str = str + next + space + orange + "Description: |r" + blue + text + "|r"
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.00, 0.00, 3600.00, str)
endif
endfunction
// Returns the proper Z height of point p(x/y).
function Missile_GetLocZ takes real x, real y returns real
call MoveLocation(udg_MissileLocZ, x, y)
return GetLocationZ(udg_MissileLocZ)
endfunction
function Missile_GetArc takes integer index returns real
return Tan(udg_Missile__Arc*bj_DEGTORAD)*udg_Missile_AB_Distance[index]/4
endfunction
function Missile_GetCurve takes integer index returns real
return Tan(udg_Missile__Curve*bj_DEGTORAD)*udg_Missile_AB_Distance[index]
endfunction
// Converts fly time to missile speed.
// Doesn't take acceleration into account.
function Missile_GetFlyTime takes integer index returns real
return (udg_Missile_AB_Distance[index] - udg_Missile_AB_Traveled[index])/RMaxBJ(0.0000001, udg_Missile__FlyTime)
endfunction
function Missile_Math takes integer index returns nothing
local real dx
local real dy
local real iz// Allows to set an impact offset in z.
if udg_Missile_Target[index] != null and GetUnitTypeId(udg_Missile_Target[index]) != 0 then
set udg_Missile_OriginX[index] = GetUnitX(udg_Missile_Dummy[index])
set udg_Missile_OriginY[index] = GetUnitY(udg_Missile_Dummy[index])
set udg_Missile_OriginZ[index] = GetUnitFlyHeight(udg_Missile_Dummy[index])
set udg_Missile_ImpactX[index] = GetUnitX(udg_Missile_Target[index])
set udg_Missile_ImpactY[index] = GetUnitY(udg_Missile_Target[index])
set udg_Missile_AB_Traveled[index] = 0.00
// Once you set a homing target you'll lose arc & curve settings.
// That may get patched in the next version update.
set udg_Missile_Open[index] = 0.00
set udg_Missile_Height[index] = 0.00
set udg_Missile_Curve[index] = 0.00
set udg_Missile_Arc[index] = 0.00
set iz = GetUnitFlyHeight(udg_Missile_Target[index]) + udg_Missile_ImpactZ[index]
else
set iz = udg_Missile_ImpactZ[index]
endif
loop
set dx = udg_Missile_OriginX[index] - udg_Missile_ImpactX[index]
set dy = udg_Missile_OriginY[index] - udg_Missile_ImpactY[index]
set dx = dx*dx + dy*dy
set dy = SquareRoot(dx)
exitwhen dx != 0.00 and dy != 0.00// Check for parabola limits.
set udg_Missile_OriginX[index] = udg_Missile_OriginX[index] + 0.01
endloop
set udg_Missile_A_Z[index] = Missile_GetLocZ(udg_Missile_OriginX[index], udg_Missile_OriginY[index])
set udg_Missile_B_Z[index] = Missile_GetLocZ(udg_Missile_ImpactX[index], udg_Missile_ImpactY[index])
set udg_Missile_AB_Square[index] = dx
set udg_Missile_AB_Distance[index] = dy
set udg_Missile_AB_Angle[index] = Atan2(udg_Missile_ImpactY[index] - udg_Missile_OriginY[index], udg_Missile_ImpactX[index] - udg_Missile_OriginX[index])
set udg_Missile_AB_Pitch[index] = ((iz + udg_Missile_B_Z[index]) - (udg_Missile_OriginZ[index] + udg_Missile_A_Z[index]))/dy
endfunction
// Doesn't include all array types. Only those which require a reset.
function Missile_ResetArrays takes integer index returns nothing
set udg_Missile_AB_Traveled[index] = 0.00
set udg_Missile_Acceleration[index] = 0.00
set udg_Missile_Arc[index] = 0.00
set udg_Missile_Collision[index] = 0.00
set udg_Missile_Curve[index] = 0.00
set udg_Missile_CurveX[index] = 0.00
set udg_Missile_CurveY[index] = 0.00
set udg_Missile_Damage[index] = 0.00
set udg_Missile_Data[index] = 0
set udg_Missile_Distance[index] = 0.00
set udg_Missile_Dummy[index] = null
set udg_Missile_Effect[index] = null
set udg_Missile_Model[index] = null
set udg_Missile_FlyTime[index] = 0.00
set udg_Missile_Height[index] = 0.00
set udg_Missile_OriginZ[index] = 0.00
set udg_Missile_ImpactZ[index] = 0.00
set udg_Missile_OnUnit[index] = null
set udg_Missile_OnDest[index] = null
set udg_Missile_OnPeriodic[index] = null
set udg_Missile_OnFinish[index] = null
set udg_Missile_OnRemove[index] = null
set udg_Missile_Open[index] = 0.00
set udg_Missile_Owner[index] = null
set udg_Missile_Recycle[index] = false
set udg_Missile_Scale[index] = 1.00
set udg_Missile_Source[index] = null
set udg_Missile_Speed[index] = 0.00
set udg_Missile_Target[index] = null
set udg_Missile_Turn[index] = 0.00
set udg_Missile_WantDestroy[index] = false
endfunction
function Missile_SaveUserData takes integer index returns nothing
local boolean math = false
set udg_Missile_OnUnit[index] = udg_Missile__OnCollideUnit
set udg_Missile_OnDest[index] = udg_Missile__OnCollideDestructable
set udg_Missile_OnPeriodic[index] = udg_Missile__OnPeriodic
set udg_Missile_OnFinish[index] = udg_Missile__OnFinish
set udg_Missile_OnRemove[index] = udg_Missile__OnRemove
set udg_Missile_Source[index] = udg_Missile__Source
set udg_Missile_Target[index] = udg_Missile__Target
set udg_Missile_Owner[index] = udg_Missile__Owner
set udg_Missile_Data[index] = udg_Missile__Data
set udg_Missile_Collision[index] = udg_Missile__Collision
set udg_Missile_WantDestroy[index] = udg_Missile__WantDestroy
set udg_Missile_Damage[index] = udg_Missile__Damage
set udg_Missile_Acceleration[index] = udg_Missile__Acceleration
set udg_Missile_Turn[index] = udg_Missile__Turn
// The user set a new origin point.
if udg_Missile__Origin != null then
set udg_Missile_OriginX[index] = GetLocationX(udg_Missile__Origin)
set udg_Missile_OriginY[index] = GetLocationY(udg_Missile__Origin)
call RemoveLocation(udg_Missile__Origin)
set udg_Missile__Origin = null
set math = true
endif
if udg_Missile_OriginZ[index] != udg_Missile__OriginZ then
set udg_Missile_OriginZ[index] = udg_Missile__OriginZ
set math = true
endif
if udg_Missile__Impact != null then
set udg_Missile_ImpactX[index] = GetLocationX(udg_Missile__Impact)
set udg_Missile_ImpactY[index] = GetLocationY(udg_Missile__Impact)
call RemoveLocation(udg_Missile__Impact)
set udg_Missile__Impact = null
set math = true
endif
if udg_Missile_ImpactZ[index] != udg_Missile__ImpactZ then
set udg_Missile_ImpactZ[index] = udg_Missile__ImpactZ
set math = true
endif
if math then
call Missile_Math(index)
endif
// The user defined a new model.
if udg_Missile_Model[index] != udg_Missile__Model then
set udg_Missile_Model[index] = udg_Missile__Model
if udg_Missile_Effect[index] != null then
call DestroyEffect(udg_Missile_Effect[index])
endif
if StringLength(udg_Missile__Model) > 0 then
set udg_Missile_Effect[index] = AddSpecialEffectTarget(udg_Missile__Model, udg_Missile_Dummy[index], "origin")
else
set udg_Missile_Effect[index] = null
endif
endif
// Default scaling on Missile_Create is 1.00.
if udg_Missile_Scale[index] != udg_Missile__Scale then
set udg_Missile_Scale[index] = udg_Missile__Scale
call SetUnitScale(udg_Missile_Dummy[index], udg_Missile__Scale, 0.00, 0.00)
endif
if udg_Missile_Curve[index] != udg_Missile__Curve then
set udg_Missile_Curve[index] = udg_Missile__Curve
set udg_Missile_Open[index] = Missile_GetCurve(index)
else
set udg_Missile_Open[index] = udg_Missile__Open
endif
if udg_Missile_Arc[index] != udg_Missile__Arc then
set udg_Missile_Arc[index] = udg_Missile__Arc
set udg_Missile_Height[index] = Missile_GetArc(index)
else
set udg_Missile_Height[index] = udg_Missile__Height
endif
if udg_Missile_FlyTime[index] != udg_Missile__FlyTime then
set udg_Missile_FlyTime[index] = udg_Missile__FlyTime
set udg_Missile_Speed[index] = Missile_GetFlyTime(index)
else
set udg_Missile_Speed[index] = udg_Missile__Speed
endif
endfunction
function Missile_LoadData takes integer index returns nothing
set udg_Missile__Index = index
// Load event triggers.
set udg_Missile__OnCollideUnit = udg_Missile_OnUnit[index]
set udg_Missile__OnCollideDestructable = udg_Missile_OnDest[index]
set udg_Missile__OnPeriodic = udg_Missile_OnPeriodic[index]
set udg_Missile__OnFinish = udg_Missile_OnFinish[index]
set udg_Missile__OnRemove = udg_Missile_OnRemove[index]
// Load other handle types.
set udg_Missile__Dummy = udg_Missile_Dummy[index]
set udg_Missile__Source = udg_Missile_Source[index]
set udg_Missile__Target = udg_Missile_Target[index]
set udg_Missile__Owner = udg_Missile_Owner[index]
set udg_Missile__Damage = udg_Missile_Damage[index]
set udg_Missile__Collision = udg_Missile_Collision[index]
set udg_Missile__Model = udg_Missile_Model[index]
set udg_Missile__Data = udg_Missile_Data[index]
set udg_Missile__Scale = udg_Missile_Scale[index]
set udg_Missile__WantDestroy = udg_Missile_WantDestroy[index]
set udg_Missile__Speed = udg_Missile_Speed[index]
set udg_Missile__Acceleration = udg_Missile_Acceleration[index]
set udg_Missile__Open = udg_Missile_Open[index]
set udg_Missile__Turn = udg_Missile_Turn[index]
set udg_Missile__Height = udg_Missile_Height[index]
set udg_Missile__Angle = udg_Missile_Angle[index]
set udg_Missile__Distance = udg_Missile_Distance[index]
set udg_Missile__Arc = udg_Missile_Arc[index]
set udg_Missile__Curve = udg_Missile_Curve[index]
set udg_Missile__FlyTime = udg_Missile_FlyTime[index]
set udg_Missile__OriginZ = udg_Missile_OriginZ[index]
set udg_Missile__ImpactZ = udg_Missile_ImpactZ[index]
endfunction
function Missile_ResetScalars takes nothing returns nothing
if udg_Missile__Origin != null then
call RemoveLocation(udg_Missile__Origin)
set udg_Missile__Origin = null
endif
if udg_Missile__Impact != null then
call RemoveLocation(udg_Missile__Origin)
set udg_Missile__Impact = null
endif
set udg_Missile__WantDestroy = false
set udg_Missile__Recycle = false
set udg_Missile__OnCollideUnit = null
set udg_Missile__OnPeriodic = null
set udg_Missile__OnFinish = null
set udg_Missile__OnCollideDestructable = null
set udg_Missile__OnRemove = null
set udg_Missile__Dummy = null
set udg_Missile__Source = null
set udg_Missile__Target = null
set udg_Missile__Owner = null
set udg_Missile__Model = null
set udg_Missile__Angle = 0.00
set udg_Missile__Collision = 0.00
set udg_Missile__Damage = 0.00
set udg_Missile__Speed = 0.00
set udg_Missile__Acceleration = 0.00
set udg_Missile__Open = 0.00
set udg_Missile__Height = 0.00
set udg_Missile__Turn = 0.00
set udg_Missile__Distance = 0.00
set udg_Missile__ImpactZ = 0.00
set udg_Missile__OriginZ = 0.00
set udg_Missile__Arc = 0.00
set udg_Missile__Curve = 0.00
set udg_Missile__FlyTime = 0.00
set udg_Missile__Scale = 1.00
set udg_Missile__EventId = udg_EVENT_MISSILE_NOTHING
set udg_Missile__Data = 0
set udg_Missile__Index = 0
endfunction
//=============================================================
// Wrapper functions.
//=============================================================
function Missile_RunTrigger takes integer index, trigger trig, integer eventId returns boolean
set udg_Missile__EventId = eventId
set udg_Missile__EventIndex = index
call Missile_LoadData(index)
if TriggerEvaluate(trig) then
call TriggerExecute(trig)
call Missile_SaveUserData(index)
endif
// Just in case the user accidently changes udg_Missile__Index.
set udg_Missile__EventIndex = 0
set udg_Missile__EventId = udg_EVENT_MISSILE_NOTHING
return udg_Missile__WantDestroy
endfunction
//=============================================================
// Delayed dummy recycler. Data structure stack.
//=============================================================
// According to my tests:
// - Using KillUnit(unit) will remove the 'Aloc' effect for group enumerations.
// - Using UnitApplyTimedLife(unit, 'BTLF', 0.01) keeps on dropping the fps until you hit 0.
//
// The cleanest approach appears to be RemoveUnit(unit). Using a stack with timed dummy
// recycling helps us to properly display the attached special effects.
function Missile_UpdateStack takes nothing returns nothing
local integer index = 0
loop
exitwhen index == udg_MissileDummyCount
if udg_MissileDummyTime[index] <= 0 then
call RemoveUnit(udg_MissileDummyStack[index])
set udg_MissileDummyCount = udg_MissileDummyCount - 1
if udg_MissileDummyCount == 0 then
set udg_MissileDummyStack[index] = null
call PauseTimer(udg_MissileDummyTimer)
else
set udg_MissileDummyStack[index] = udg_MissileDummyStack[udg_MissileDummyCount]
set udg_MissileDummyTime[index] = udg_MissileDummyTime[udg_MissileDummyCount]
set udg_MissileDummyStack[udg_MissileDummyCount] = null
endif
else
set udg_MissileDummyTime[index] = udg_MissileDummyTime[index] - 1
set index = index + 1
endif
endloop
endfunction
function Missile_RecycleDummy takes unit dummy returns nothing
if GetUnitTypeId(dummy) == udg_Missile__DummyTypeId then
set udg_MissileDummyTime[udg_MissileDummyCount] = Missile_GetEffectDeathTime()// Approximate death time for special effects.
set udg_MissileDummyStack[udg_MissileDummyCount] = dummy
if udg_MissileDummyCount == 0 then
call TimerStart(udg_MissileDummyTimer, 1., true, function Missile_UpdateStack)
endif
set udg_MissileDummyCount = udg_MissileDummyCount + 1
endif
endfunction
//=============================================================
// Missile structure. Static unique doubly linked list.
//=============================================================
function Missile_SetListNextNode takes integer node, integer nextNode returns nothing
set udg_MissileNextNode[node] = nextNode
endfunction
constant function Missile_GetListNextNode takes integer node returns integer
return udg_MissileNextNode[node]
endfunction
function Missile_SetListPrevNode takes integer node, integer prevNode returns nothing
set udg_MissilePrevNode[node] = prevNode
endfunction
constant function Missile_GetListPrevNode takes integer node returns integer
return udg_MissilePrevNode[node]
endfunction
function Missile_SetListFirstNode takes integer node returns nothing
set udg_MissileNextNode[0] = node
endfunction
constant function Missile_GetListFirstNode takes nothing returns integer
return udg_MissileNextNode[0]
endfunction
function Missile_SetListLastNode takes integer node returns nothing
set udg_MissilePrevNode[0] = node
endfunction
constant function Missile_GetListLastNode takes nothing returns integer
return udg_MissilePrevNode[0]
endfunction
function Missile_ListRemoveNode takes integer node returns nothing
call Missile_SetListNextNode(Missile_GetListPrevNode(node), Missile_GetListNextNode(node))
call Missile_SetListPrevNode(Missile_GetListNextNode(node), Missile_GetListPrevNode(node))
endfunction
function Missile_ListPushNode takes integer node returns nothing
call Missile_SetListPrevNode(Missile_GetListFirstNode(), node)
call Missile_SetListNextNode(node, Missile_GetListFirstNode())
call Missile_SetListFirstNode(node)
call Missile_SetListPrevNode(node, 0)
endfunction
function Missile_AllocateNode takes nothing returns integer
local integer node = udg_MissileRecycler[0]
if node == 0 then
set node = udg_MissileNodes + 1
// Overflow
if node == JASS_MAX_ARRAY_SIZE then
call Missile_ErrorMessage(true, "Missile_AllocateNode", "udg_MissileNodes", JASS_MAX_ARRAY_SIZE, "Stack overflow!")
return 0
endif
set udg_MissileNodes = node
else
set udg_MissileRecycler[0] = udg_MissileRecycler[node]
endif
set udg_MissileAllocated[node] = true
return node
endfunction
function Missile_RecycleNode takes integer node returns nothing
set udg_MissileAllocated[node] = false
set udg_MissileRecycler[node] = udg_MissileRecycler[0]
set udg_MissileRecycler[0] = node
endfunction
//=================================================================
// Destructor & Cleanup.
//=================================================================
function Missile_Clear takes integer index returns nothing
if udg_Missile_Effect[index] != null then
call DestroyEffect(udg_Missile_Effect[index])
endif
call Missile_RecycleDummy(udg_Missile_Dummy[index])
call Missile_ResetArrays(index)
call FlushChildHashtable(udg_MissileHash, index)
endfunction
function Missile_Destroy takes integer index returns nothing
if udg_MissileAllocated[index] then
if udg_MissileLaunched[index] then
if udg_Missile_OnRemove[index] != null then
call Missile_RunTrigger(index, udg_Missile_OnRemove[index], udg_EVENT_MISSILE_REMOVE)
endif
call Missile_ListRemoveNode(index)
if Missile_GetListFirstNode() == 0 then
call PauseTimer(udg_MissileTimer)
endif
set udg_MissileLaunched[index] = false
endif
call Missile_Clear(index)
call Missile_RecycleNode(index)
else
call Missile_ErrorMessage(true, "Missile_Destroy", "udg_MissileAllocated", index, "Attempt to destroy invalid node!")
endif
endfunction
//=============================================================
// Widget collision code.
//=============================================================
// For a rectangle collision z values are
// very inaccurate, hence they are completly ignored.
function Missile_IsWidgetInRectangleRad takes integer index, widget w returns boolean
local real wx = GetWidgetX(w)
local real wy = GetWidgetY(w)
local real dx = udg_Missile_PosX[index] - udg_Missile_PrevX[index]
local real dy = udg_Missile_PosY[index] - udg_Missile_PrevY[index]
local real s = (dx*(wx - udg_Missile_PrevX[index]) + dy*(wy - udg_Missile_PrevY[index]))/RMaxBJ(0.0001, (dx*dx + dy*dy))
if s < 0.00 then
set s = 0.00
elseif s > 1.00 then
set s = 1.00
endif
set dx = (udg_Missile_PrevX[index] + s*dx) - wx
set dy = (udg_Missile_PrevY[index] + s*dy) - wy
return dx*dx + dy*dy <= udg_Missile_Collision[index]*udg_Missile_Collision[index]
endfunction
function Missile_IsWidgetInRange takes integer index, widget w, real wz, real distance returns boolean
local real wx = GetWidgetX(w)
local real wy = GetWidgetY(w)
local real dz = Missile_GetLocZ(wx, wy) - udg_Missile_TerrainZ[index]
return IsUnitInRangeXY(udg_Missile_Dummy[index], wx, wy, distance) and dz + wz >= udg_Missile_PosZ[index] and dz <= udg_Missile_PosZ[index] + distance
endfunction
function Missile_SetRectRectangle takes integer index returns rect
local real x1 = udg_Missile_PrevX[index]
local real y1 = udg_Missile_PrevY[index]
local real x2 = udg_Missile_PosX[index]
local real y2 = udg_Missile_PosY[index]
local real d = udg_Missile_Collision[index] + Missile_GetMaxCollision()
// What is min, what is max ...
if x1 < x2 then
if y1 < y2 then
call SetRect(udg_MissileRect, x1 - d, y1 - d, x2 + d, y2 + d)
else
call SetRect(udg_MissileRect, x1 - d, y2 - d, x2 + d, y1 + d)
endif
else
if y1 < y2 then
call SetRect(udg_MissileRect, x2 - d, y1 - d, x1 + d, y2 + d)
else
call SetRect(udg_MissileRect, x2 - d, y2 - d, x1 + d, y1 + d)
endif
endif
return udg_MissileRect
endfunction
function Missile_SetRectCircle takes integer index returns rect
local real x = udg_Missile_PosX[index]
local real y = udg_Missile_PosY[index]
local real d = udg_Missile_Collision[index] + Missile_GetMaxCollision()
call SetRect(udg_MissileRect, x - d, y - d, x + d, y + d)
return udg_MissileRect
endfunction
function Missile_RunUnitCollision takes integer index returns nothing
local real size = udg_Missile_Collision[index]
local boolean rectangle = size < udg_Missile_Speed[index]*Missile_GetTimerTimeout()
local real collideZ
local boolean hit
local unit u
if rectangle then
call GroupEnumUnitsInRect(udg_MissileGroup, Missile_SetRectRectangle(index), null)
else
call GroupEnumUnitsInRange(udg_MissileGroup, udg_Missile_PosX[index], udg_Missile_PosY[index], size + Missile_GetMaxCollision(), null)
endif
loop
set u = FirstOfGroup(udg_MissileGroup)
exitwhen u == null
call GroupRemoveUnit(udg_MissileGroup, u)
// Chech if missile already hit this unit.
if not HaveSavedHandle(udg_MissileHash, index, GetHandleId(u)) then
set hit = false
// Evaluate rectangle collision.
if rectangle then
set hit = Missile_IsWidgetInRectangleRad(index, u)
// Evaluate circular collision.
elseif IsUnitInRange(u, udg_Missile_Dummy[index], size) then
set collideZ = Missile_GetLocZ(GetUnitX(u), GetUnitY(u)) + GetUnitFlyHeight(u) - udg_Missile_TerrainZ[index]
set hit = (collideZ + Missile_GetUnitBodySize(u) >= udg_Missile_PosZ[index] - size) and (collideZ <= udg_Missile_PosZ[index] + size)
endif
if hit then
call SaveUnitHandle(udg_MissileHash, index, GetHandleId(u), u)
set udg_Missile__UnitHit = u
if Missile_RunTrigger(index, udg_Missile_OnUnit[index], udg_EVENT_MISSILE_COLLIDE_UNIT) then
call Missile_Destroy(index)
exitwhen true
endif
endif
endif
endloop
set u = null
set udg_Missile__UnitHit = null
endfunction
function Missile_EnumDestructables takes nothing returns nothing
local integer index = udg_Missile__Index
local destructable d = GetEnumDestructable()
local boolean hit
// Enum trigger action threads can't be canceled. Therefore
// the code must check for each trigger execution if the index is still allocated.
if udg_MissileAllocated[index] and not HaveSavedHandle(udg_MissileHash, index, GetHandleId(d)) then
set hit = false
// Run rectangle collision.
if udg_Missile_Collision[index] < udg_Missile_Speed[index]*Missile_GetTimerTimeout() then
set hit = Missile_IsWidgetInRectangleRad(index, d)
else
// Run circular collision.
set hit = Missile_IsWidgetInRange(index, d, Missile_GetDestructableHeight(d), udg_Missile_Collision[index])
endif
if hit then
call SaveDestructableHandle(udg_MissileHash, index, GetHandleId(d), d)
set udg_Missile__DestructableHit = d
if Missile_RunTrigger(index, udg_Missile_OnDest[index], udg_EVENT_MISSILE_COLLIDE_DEST) then
call Missile_Destroy(index)
endif
set udg_Missile__DestructableHit = null
endif
endif
set d = null
endfunction
function Missile_RunDestructableCollision takes integer index returns nothing
set udg_Missile__Index = index
if udg_Missile_Collision[index] < udg_Missile_Speed[index]*Missile_GetTimerTimeout() then
call EnumDestructablesInRect(Missile_SetRectRectangle(index), null, function Missile_EnumDestructables)
else
call EnumDestructablesInRect(Missile_SetRectCircle(index), null, function Missile_EnumDestructables)
endif
endfunction
//=============================================================
// Core.
//=============================================================
function Missile_UpdatePosition takes integer index returns nothing
local real velocity = udg_Missile_Speed[index]*Missile_GetTimerTimeout()
local real turn = udg_Missile_Turn[index]*Missile_GetTimerTimeout()
local unit missile = udg_Missile_Dummy[index]
local real posX = GetUnitX(missile)
local real posY = GetUnitY(missile)
local real posZ
local real angle
local real point // Current point on the parabola curve.
local real pitch
local real square
local real distance
local real curveX
local real curveY
// Save previous, respectively current missile position.
// This is required for a possible rectangle collision.
set udg_Missile_PrevX[index] = posX
set udg_Missile_PrevY[index] = posY
// For further calculations local real velocity is used instead of speed[index].
set udg_Missile_Speed[index] = udg_Missile_Speed[index] + udg_Missile_Acceleration[index]
// Update missile guidance to its intended target.
if udg_Missile_Target[index] != null then
if GetUnitTypeId(udg_Missile_Target[index]) == 0 then
set udg_Missile_Target[index] = null
else
call Missile_Math(index)
endif
endif
// For read-abilty improvement, eventually also performance.
set square = udg_Missile_AB_Square[index]
set distance = udg_Missile_AB_Distance[index]
set point = udg_Missile_AB_Traveled[index]
// Update the missile angle dependant on the turn ratio.
if turn != 0.00 and Cos(udg_Missile_Angle[index] - udg_Missile_AB_Angle[index]) < Cos(turn) then
if Sin(udg_Missile_AB_Angle[index] - udg_Missile_Angle[index]) < 0.00 then
set udg_Missile_Angle[index] = udg_Missile_Angle[index] - turn
else
set udg_Missile_Angle[index] = udg_Missile_Angle[index] + turn
endif
else
set udg_Missile_Angle[index] = udg_Missile_AB_Angle[index]
endif
// Update the missile point on the parabola.
set udg_Missile_Recycle[index] = point + velocity >= distance
if udg_Missile_Recycle[index] then
set udg_Missile_Distance[index] = udg_Missile_Distance[index] + distance - point
set point = udg_Missile_AB_Distance[index]
else
set udg_Missile_Distance[index] = udg_Missile_Distance[index] + velocity
set point = point + velocity
endif
set udg_Missile_AB_Traveled[index] = point
// Set new position in plane x & y, as well as the facing angle in radians.
set angle = udg_Missile_Angle[index]
set posX = posX + velocity*Cos(angle)
set posY = posY + velocity*Sin(angle)
// Update point(x/y) if a curving trajectory is defined.
if udg_Missile_Open[index] != 0.00 then
set velocity = 4*udg_Missile_Open[index]*point*(distance - point)/square
set curveX = velocity*Cos(angle + bj_PI/2)
set curveY = velocity*Sin(angle + bj_PI/2)
set posX = posX + velocity*Cos(angle + bj_PI/2) - udg_Missile_CurveX[index]
set posY = posY + velocity*Sin(angle + bj_PI/2) - udg_Missile_CurveY[index]
set angle = angle + Atan(-((4*udg_Missile_Open[index])*(2*point - distance))/square)
// Save the current offset in plane x / y.
set udg_Missile_CurveX[index] = curveX
set udg_Missile_CurveY[index] = curveY
endif
// Update point(x,y,z) if an arc or height is defined.
set pitch = udg_Missile_AB_Pitch[index]
set udg_Missile_TerrainZ[index] = Missile_GetLocZ(posX, posY)
if udg_Missile_Height[index] == 0.00 and pitch == 0.00 then
set posZ = udg_Missile_OriginZ[index] + udg_Missile_A_Z[index] - udg_Missile_TerrainZ[index]
else
set posZ = udg_Missile_OriginZ[index] + udg_Missile_A_Z[index] - udg_Missile_TerrainZ[index] + pitch*point
set pitch = Atan(pitch)*bj_RADTODEG
if udg_Missile_Height[index] != 0.00 then
set posZ = posZ + 4*udg_Missile_Height[index]*point*(distance - point)/square
set pitch = pitch - Atan(((4*udg_Missile_Height[index])*(2*point - distance))/square)*bj_RADTODEG
endif
endif
// Update the pitch angle of the dummy unit.
if GetUnitTypeId(missile) == udg_Missile__DummyTypeId then
call SetUnitAnimationByIndex(missile, R2I(pitch + 90.5))
endif
set udg_Missile_PosX[index] = posX
set udg_Missile_PosY[index] = posY
set udg_Missile_PosZ[index] = posZ
// Finally update the missile dummy position and facing angle.
call SetUnitFacing(missile, angle*bj_RADTODEG)
call SetUnitFlyHeight(missile, posZ, 0.00)
if posX < udg_MissileMaxX and posX > udg_MissileMinX and posY < udg_MissileMaxY and posY > udg_MissileMinY then
call SetUnitX(missile, posX)
call SetUnitY(missile, posY)
endif
set missile = null
endfunction
function Missile_Core takes nothing returns boolean
local integer loops = 0 // Iteration counter.
local integer limit = 100 // Maximum iterations per trigger evaluate.
local integer index
local integer next
loop
exitwhen udg_Missile__Index == 0
exitwhen limit == loops
set index = udg_Missile__Index
set next = Missile_GetListNextNode(index)
if udg_Missile_WantDestroy[index] then
call Missile_Destroy(index)
else
set udg_Missile__Index = next
call Missile_UpdatePosition(index)
set udg_Missile__Index = index
// Run unit collision code.
if udg_MissileAllocated[index] and udg_Missile_OnUnit[index] != null and udg_Missile_Collision[index] > 0.00 then
call Missile_RunUnitCollision(index)
endif
// Run destructable collision code.
if udg_MissileAllocated[index] and udg_Missile_OnDest[index] != null and udg_Missile_Collision[index] > 0.00 then
call Missile_RunDestructableCollision(index)
endif
// Runs when the impact point is reached.
if udg_MissileAllocated[index] and udg_Missile_Recycle[index] then
if udg_Missile_OnFinish[index] != null then
if Missile_RunTrigger(index, udg_Missile_OnFinish[index], udg_EVENT_MISSILE_FINISH) then
call Missile_Destroy(index)
endif
else
call Missile_Destroy(index)
endif
endif
// Runs periodically every timer timeout.
if udg_MissileAllocated[index] and udg_Missile_OnPeriodic[index] != null then
if Missile_RunTrigger(index, udg_Missile_OnPeriodic[index], udg_EVENT_MISSILE_PERIODIC) then
call Missile_Destroy(index)
endif
endif
endif
set loops = loops + 1
set udg_Missile__Index = next
endloop
return udg_Missile__Index == 0
endfunction
// Missile_GetTimerTimeout()
function Missile_OnPeriodic takes nothing returns nothing
set udg_Missile__Index = Missile_GetListFirstNode()
loop
exitwhen TriggerEvaluate(udg_MissileCore)
endloop
call Missile_ResetScalars()
endfunction
function Missile_InitNewMissile takes integer index returns nothing
local real originX = GetLocationX(udg_Missile__Origin)
local real originY = GetLocationY(udg_Missile__Origin)
local real face = Atan2(GetLocationY(udg_Missile__Impact) - originY, GetLocationX(udg_Missile__Impact) - originX)*bj_RADTODEG
// A user may pass his/her own units as projectile dummies.
if udg_Missile__Dummy == null then
set bj_lastCreatedUnit = CreateUnit(Missile_GetDummyOwner(), udg_Missile__DummyTypeId, originX, originY, face)
set udg_Missile__Dummy = bj_lastCreatedUnit// GUI compatibility for function CreateUnitAtLocSaveLast.
call UnitAddAbility(udg_Missile__Dummy, 'Aloc')
call PauseUnit(udg_Missile__Dummy, true)
endif
// Enables fly height manipulation for the dummy.
if UnitAddAbility(udg_Missile__Dummy, 'Amrf') and UnitRemoveAbility(udg_Missile__Dummy, 'Amrf') then
endif
call SetUnitFlyHeight(udg_Missile__Dummy, udg_Missile__OriginZ, 0.00)
set udg_Missile_Dummy[index] = udg_Missile__Dummy
set udg_Missile_Scale[index] = 1.00
set udg_Missile_Angle[index] = GetUnitFacing(udg_Missile__Dummy)*bj_DEGTORAD
// Prevent the missile from colliding with itself.
call SaveUnitHandle(udg_MissileHash, index, GetHandleId(udg_Missile__Dummy), udg_Missile__Dummy)
endfunction
function Missile_BuildLocations takes nothing returns boolean
if udg_Missile__Origin == null then
// Build from dummy position.
if udg_Missile__Dummy != null then
set udg_Missile__Origin = Location(GetUnitX(udg_Missile__Dummy), GetUnitY(udg_Missile__Dummy))
// Build from source position
elseif udg_Missile__Source != null then
set udg_Missile__Origin = Location(GetUnitX(udg_Missile__Source), GetUnitY(udg_Missile__Source))
else
call Missile_ErrorMessage(true, "Missile_BuildLocations", "Missile__Origin", udg_Missile__Index, "Missile is unable to build an origin location.
The process requires either a target or source unit.")
return false
endif
endif
if udg_Missile__Impact == null then
// Build from target position.
if GetUnitTypeId(udg_Missile__Target) != 0 then
set udg_Missile__Impact = Location(GetUnitX(udg_Missile__Target), GetUnitY(udg_Missile__Target))
else
// Build from origin using angle ( radians! ) and distance.
set udg_Missile__Impact = PolarProjectionBJ(udg_Missile__Origin, udg_Missile__Distance, udg_Missile__Angle*bj_RADTODEG)
endif
endif
return true
endfunction
// Action function of trigger Missile.
function Missile_Launch takes nothing returns nothing
local integer index = udg_Missile__Index
if not udg_MissileAllocated[index] or udg_MissileLaunched[index] then
// This is an invalid situation caused by faulty
// usage of the Missile API. Missile_Launch was executed
// without a previous execution of Missile_Create.
// Error identification.
call Missile_ErrorMessage(udg_MissileLaunched[index], "Missile_Launch", "Missile_Launched", index, "Attempt to double launch a missile!
Make sure you use Run Missile Configurate <gen> - Your missile settings - Run Missile <gen> syntax.")
call Missile_ErrorMessage(not udg_MissileAllocated[index], "Missile_Launch", "Missile__Index ", index, "Attempt to launch invalid missile index!
Make sure you use Run Missile Configurate <gen> - Your missile settings - Run Missile <gen> syntax.")
// Check if Missile has to build an origin or impact location.
elseif ((udg_Missile__Origin == null) or (udg_Missile__Impact == null)) and not Missile_BuildLocations() then
call Missile_Destroy(index)
else
set udg_MissileLaunched[index] = true
if Missile_GetListFirstNode() == 0 then
call TimerStart(udg_MissileTimer, Missile_GetTimerTimeout(), true, function Missile_OnPeriodic)
endif
call Missile_ListPushNode(index)
call Missile_InitNewMissile(index)
call Missile_SaveUserData(index)
endif
call Missile_ResetScalars()
if udg_Missile__EventIndex != 0 then
call Missile_LoadData(udg_Missile__EventIndex)
endif
endfunction
// Action function of trigger Missile Configurate.
function Missile_Create takes nothing returns nothing
// In most cases udg_Missile__Index is 0, thus not allocated.
if udg_MissileAllocated[udg_Missile__Index] then
// Check if Missile_Create runs from inside a Missile event trigger.
if udg_Missile__EventIndex == udg_Missile__Index then
// Save all data from scalar to array variables.
call Missile_SaveUserData(udg_Missile__EventIndex)
elseif not udg_MissileLaunched[udg_Missile__Index] then
// This is an invalid situation caused by faulty
// usage of the Missile API. Missile_Create was executed twice
// without launching the previously created index.
// Missile compensates for that error by destroying
// the forgotten index.
call Missile_Destroy(udg_Missile__Index)
// Print it for the user.
call Missile_ErrorMessage(true, "Missile_Create", "Missile_Launched", udg_Missile__Index, "You forgot to launch the previous created missile!
Make sure you use Run Missile Configurate <gen> - Your missile settings - Run Missile <gen> syntax.")
endif
endif
call Missile_ResetScalars()
set udg_Missile__Index = Missile_AllocateNode()
endfunction
//===========================================================================
function InitTrig_Missile takes nothing returns nothing
if gg_trg_Missile != null then
return// Missile has already been initialized.
endif
set udg_MissileHash = InitHashtable()
set udg_MissileCore = CreateTrigger()
set udg_MissileRect = GetWorldBounds()
set udg_MissileLocZ = Location(0.00, 0.00)
// It's necessary to prevent missiles, units in general, from leaving map boundaries.
set udg_MissileMaxX = R2I(GetRectMaxX(udg_MissileRect)) - 197
set udg_MissileMaxY = R2I(GetRectMaxY(udg_MissileRect)) - 197
set udg_MissileMinX = R2I(GetRectMinX(udg_MissileRect)) + 197
set udg_MissileMinY = R2I(GetRectMinY(udg_MissileRect)) + 197
// Trigger that controlls the trajectory of all missiles.
call TriggerAddCondition(udg_MissileCore, Condition(function Missile_Core))
// Run the configuration trigger before the first missile is created.
call TriggerExecute(gg_trg_Missile_Configurate)
call TriggerClearActions(gg_trg_Missile_Configurate)
call DestroyTrigger(gg_trg_Missile_Configurate)
// Transform the configurate trigger into the index allocator.
set gg_trg_Missile_Configurate = CreateTrigger()
call TriggerAddAction(gg_trg_Missile_Configurate, function Missile_Create)
// Build the launching trigger for missiles.
set gg_trg_Missile = CreateTrigger()
call TriggerAddAction(gg_trg_Missile, function Missile_Launch)
// Set the missile system ready.
call Missile_ResetScalars()
endfunction
//TESH.scrollpos=45
//TESH.alwaysfold=0
function Trig_Fireball_Actions_Copy_Func005Func001C takes nothing returns boolean
if ( not ( udg_Missile__EventId == udg_EVENT_MISSILE_COLLIDE_UNIT ) ) then
return false
endif
if ( not ( IsUnitEnemy(udg_Missile__UnitHit, udg_Missile__Owner) == true ) ) then
return false
endif
if ( not ( IsUnitAliveBJ(udg_Missile__UnitHit) == true ) ) then
return false
endif
return true
endfunction
function Trig_Fireball_Actions_Copy_Func005Func002Func002002003001 takes nothing returns boolean
return ( IsUnitEnemy(GetFilterUnit(), udg_Missile__Owner) == true )
endfunction
function Trig_Fireball_Actions_Copy_Func005Func002Func002002003002 takes nothing returns boolean
return ( IsUnitAliveBJ(GetFilterUnit()) == true )
endfunction
function Trig_Fireball_Actions_Copy_Func005Func002Func002002003 takes nothing returns boolean
return GetBooleanAnd( Trig_Fireball_Actions_Copy_Func005Func002Func002002003001(), Trig_Fireball_Actions_Copy_Func005Func002Func002002003002() )
endfunction
function Trig_Fireball_Actions_Copy_Func005Func002Func003A takes nothing returns nothing
call UnitDamageTargetBJ( udg_Missile__Source, GetEnumUnit(), udg_Missile__Damage, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL )
endfunction
function Trig_Fireball_Actions_Copy_Func005Func002C takes nothing returns boolean
if ( not ( udg_Missile__Data == 1 ) ) then
return false
endif
return true
endfunction
function Trig_Fireball_Actions_Copy_Func005C takes nothing returns boolean
if ( not ( udg_Missile__EventId == udg_EVENT_MISSILE_REMOVE ) ) then
return false
endif
return true
endfunction
function Trig_Fireball_Actions_Copy_Actions takes nothing returns nothing
// As you can see Missile__EventId allows you
// to identify which event trigger dispatched.
// Therefore you can run all actions from one trigger function.
// Of course you can also seperate triggers into different triggers.
if ( Trig_Fireball_Actions_Copy_Func005C() ) then
if ( Trig_Fireball_Actions_Copy_Func005Func002C() ) then
// Create more fireballs
// Reference to Missile__Dummy will be removed
// Once you call Run Missile Configurate <gen>
set udg_Missile__TempLoc = GetUnitLoc(udg_Missile__Dummy)
set bj_forLoopAIndex = 1
set bj_forLoopAIndexEnd = 6
loop
exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
call TriggerExecute( gg_trg_Missile_Configurate )
set udg_Missile__Origin = Location(GetLocationX(udg_Missile__TempLoc), GetLocationY(udg_Missile__TempLoc))
set udg_Missile__Impact = PolarProjectionBJ(udg_Missile__Origin, 450.00, ( 60.00 * I2R(GetForLoopIndexA()) ))
set udg_Missile__ImpactZ = 50.00
set udg_Missile__Height = 350.00
set udg_Missile__OriginZ = 50.00
set udg_Missile__Speed = 500.00
set udg_Missile__Damage = 150.00
set udg_Missile__Source = udg_Missile_Source[udg_Missile__EventIndex]
set udg_Missile__Owner = udg_Missile_Owner[udg_Missile__EventIndex]
set udg_Missile__Model = "Abilities\\Weapons\\FireBallMissile\\FireBallMissile.mdl"
set udg_Missile__OnCollideUnit = gg_trg_Fireball_Actions
set udg_Missile__OnRemove = gg_trg_Fireball_Actions
set udg_Missile__Data = 2
call TriggerExecute( gg_trg_Missile )
set bj_forLoopAIndex = bj_forLoopAIndex + 1
endloop
call RemoveLocation(udg_Missile__TempLoc)
set udg_Missile__TempLoc = null
else
set udg_Missile__TempLoc = GetUnitLoc(udg_Missile__Dummy)
set udg_Temp_Group = GetUnitsInRangeOfLocMatching(128.00, udg_Missile__TempLoc, Condition(function Trig_Fireball_Actions_Copy_Func005Func002Func002002003))
call ForGroupBJ( udg_Temp_Group, function Trig_Fireball_Actions_Copy_Func005Func002Func003A )
call AddSpecialEffectLocBJ( udg_Missile__TempLoc, "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl" )
call DestroyEffectBJ( GetLastCreatedEffectBJ() )
call DestroyGroup(udg_Temp_Group)
call RemoveLocation(udg_Missile__TempLoc)
set udg_Missile__TempLoc = null
endif
else
if ( Trig_Fireball_Actions_Copy_Func005Func001C() ) then
// See how easy damaging got.
call UnitDamageTargetBJ( udg_Missile__Source, udg_Missile__UnitHit, udg_Missile__Damage, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL )
set udg_Missile__WantDestroy = true
else
endif
endif
endfunction
//===========================================================================
function InitTrig_Fireball_Actions_Copy takes nothing returns nothing
set gg_trg_Fireball_Actions_Copy = CreateTrigger( )
call TriggerAddAction( gg_trg_Fireball_Actions_Copy, function Trig_Fireball_Actions_Copy_Actions )
endfunction
function ErrorMessage takes string error, player whichPlayer returns nothing
if udg_ErrorSound == null then
set udg_ErrorSound = CreateSoundFromLabel("NoManaHuman",false,false,false,10,10)
endif
set error = "\n\n\n\n\n\n|cffffcc00"+error+"|r"
if GetLocalPlayer()==whichPlayer then
if TimerGetRemaining(udg_MessageTimer) == 0.00 then
call StartTimerBJ( udg_MessageTimer, false, 5.00 )
call ClearTextMessages()
call DisplayTimedTextToPlayer(whichPlayer,0.52,0.96,2,error)
//call StopSound(udg_ErrorSound, false, true)
call StartSound(udg_ErrorSound)
endif
endif
endfunction