- Joined
- Nov 3, 2018
- Messages
- 79
as a casual user with knowledge only to gui this looks like basic chinese to me
but there is so much potentail here! hope it gets approved
but there is so much potentail here! hope it gets approved
Do not get intimidated by the complexity of this resource! While there are a multitude of API functions, you can build your first systems with just a few lines of code, like it is done in the examples of the Test Map. ALICE is also packaged with ready-to use libraries that provide a solid starting point for physics and missile systems. |
--The callback function on collision with the barrier:
local function ReflectProjectile(barrier, shell, x, y, z, normalSpeed, __, __)
local phi, theta = ALICE_PairGetAngle3D()
local shieldEffect = AddSpecialEffect("Abilities\\Spells\\Undead\\ReplenishMana\\ReplenishManaCasterOverhead.mdl", x, y)
BlzSetSpecialEffectZ(shieldEffect, z)
BlzSetSpecialEffectYaw(shieldEffect, phi)
BlzSetSpecialEffectPitch(shieldEffect, -theta + bj_PI/2)
BlzSetSpecialEffectAlpha(shieldEffect, math.min(128, normalSpeed // 2))
BlzSetSpecialEffectScale(shieldEffect, 1.2)
DestroyEffect(shieldEffect)
end
--This is the definition of the reflective barrier object:
ReflectiveBarrier = {
--These fields are used by ALICE itself.
identifier = "reflectiveBarrier",
interactions = {
projectile = CAT_GizmoCollisionCheck3D --This is a collision detection function included in the collisions library.
},
radius = 200,
bindToOrder = "starfall",
zOffset = 50,
--These are additional fields used by the collisions library.
onGizmoCollision = {
shell = CAT_GizmoBounce3D,
other = CAT_GizmoDevour3D
},
onGizmoCallback = ReflectProjectile,
mass = 500,
collisionRadius = 160,
elasticity = 0.2,
}
ReflectiveBarrier.__index = ReflectiveBarrier
local function CreateReflectiveBarrier()
if GetSpellAbilityId() ~= FourCC("Ashi") then
return
end
local barrier = {}
setmetatable(barrier, ReflectiveBarrier)
local u = GetSpellAbilityUnit()
barrier.anchor = u --The barrier becomes attached to Jaina.
--This creates the actor for the ReflectiveBarrier table.
ALICE_Create(barrier)
end
Feature | Description |
---|---|
Automatic Type Detection | ALICE supports any type of object passed into it, although most of its features specifically support units, destructables, items, and gizmos. Gizmos are defined as tables with coordinate fields and a special effect (missiles and such). ALICE automatically detects the types passed into it and uses the correct functions to retrieve their positions and other properties. |
Debug API | ALICE features an extensive Debug API. By typing "downtherabbithole", you can enable debug mode and select objects to get a tooltip that displays information about the actors attached to it. While selected, all interactions are shown by a green lightning effect whenever they are evaluated. You can also use hotkeys to pause the cycle or go step-by-step. You can combine the ALICE debug mode with Eikonium's Debug Utils. |
High performance | Unlike most other systems, ALICE's core avoids using enum functions entirely. Most missile systems, for example, would search for collisions with units by calling GroupEnumUnitsInRange repeatedly. But calling natives is slow and the process of calling a function repeatedly, even if there is no unit close to the missile, is inefficient itself. Think of it this way: Calling GroupEnumUnitsInRange on every iteration is like having the most advanced GPS system there is installed in your car, but then determining the time until arrival by having a kid on the back-seat ask "Are we there yet?" over and over again. ALICE instead divides the map into a grid of cells (spatial hashing), checks interaction ranges with other objects individually, and uses variable interaction intervals to drastically improve performance. |
Enum functions | While the native functions only allow enumeration of units, destructables, and items, ALICE's Enum API allows for efficient enumeration of any type of object. Although the enum functions are significantly slower than their native counterparts, the fact that they compile the objects into a Lua table instead of a group almost cancels out the speed difference, and even makes them faster in some situations. It also makes those functions much easier to work with. |
Self-interactions and Callbacks | All restaurants serve water. Sometimes, we just want to execute code on a single object. ALICE allows for this with its self-interaction and callback APIs. A self-interaction is a periodic function that only affects an object itself. |
Async mode | Since ALICE is nothing but a giant table rearrangement machine, it can be run completely asynchronously (as long as the code executed with it is async-safe). |
Extensive documentation | All API functions are fully documented and properly explained. In addition, there are manuals explaining both the basics as well as more advanced concepts. |
Support from me | If you can't figure out how something works or you encounter a bug, leave me a note and I will try my best to fix it. |
Requirement | Description |
---|---|
Total Initialization | Needs no explanation. |
Hook | Required for the default actor creation. |
HandleType | This handy little library allows ALICE to determine the correct types of the objects passed into it. Since it caches the result, it is fast and efficient. |
Precomputed Height Map (optional) | Highly recommended if you want to do any kind of 3D interactions with ALICE as it improves performance and ensures synchronicity in multiplayer. Otherwise not needed. |
CustomTooltip.toc CustomTooltip.fdf | These are the frame definition files for the actor tooltips in debug mode. Included in the test maps. |
CAT | Description |
---|---|
Objects | Requirement for all physics-related CATs. Includes the config and a collection of helper functions. |
Gizmos, Missiles, Collisions, Ballistics, Forces | These libraries contain various functions that you can use in the definitions of your objects. |
Mice | Creates an actor for each player's mouse cursor. |
Cameras | Creates an actor for each player's camera. |
Rects | Contains helper function for the creation of actors from rects. |
interactions = {milk = Drink, apple = Eat}
interactions = {
milk = Drink,
apple = Eat,
[{"steak", "grilled"}] = Eat,
[{"steak", "raw"}] = Grill
}
{steak = Eat, [{"steak", "raw"}] = Grill}
. You have to make sure that the interaction function is always unambiguous or ALICE will throw an error.local obelisk = {
x = GetSpellTargetX(),
y = GetSpellTargetY(),
owner = GetOwningPlayer(GetSpellAbilityUnit()),
visual = AddSpecialEffect(modelPath, GetSpellTargetX(), GetSpellTargetY()),
identifier = "obelisk",
interactions = {unit = HealingAura}
}
ALICE_Create(obelisk)
function StepOnMine(mine, unit)
local dist = ALICE_PairGetDistance2D()
if dist < 100 then
ALICE_Kill(mine)
ALICE_Kill(unit)
end
return (dist - 100)/522
end
interactions = {missile = DestroyMissile, self = Move}
interactions = {
missile = DestroyMissile,
self = {
Move,
Accelerate
}
}
ALICE_Create(host, identifier, interactions, {isStationary = true, radius = 200})
function FireAuraDamage(source, target)
local dist = ALICE_PairGetDistance2D()
if dist < 500 then
UnitDamageTarget(source, target, DAMAGE_AMOUNT, DAMAGE_TYPE_MAGIC, ATTACK_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
end
return 0.5
end
function OnFireAuraBuff()
local identifier = "fireAura"
local interactions = {unit = FireAuraDamage}
local flags = {radius = 500, bindToBuff = "Bfir"}
ALICE_Create(GetSpellAbilityUnit(), identifier, interactions, flags)
end
local interactions = {unit = FireAuraDamage, self = FireAuraDamage}
function OnFireAuraBuff()
local fireAura = {
identifier = "fireAura",
interactions = {unit = FireAuraDamage, self = FireAuraDamage},
anchor = GetSpellAbilityUnit(),
radius = 500,
bindToBuff = "Bfir"
}
ALICE_Create(fireAura)
end
function FireAuraDamage(fireAura, target)
local dist = ALICE_PairGetDistance2D()
if dist < 500 then
UnitDamageTarget(ALICE_GetAnchor(fireAura), ALICE_GetAnchor(target), DAMAGE_AMOUNT, DAMAGE_TYPE_MAGIC, ATTACK_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
end
return 0.5
end
function LightningChain(unitA, unitB)
local data = ALICE_PairLoadData()
if ALICE_PairGetDistance2D < 500 then
local x1, y1, x2, y2 = ALICE_PairGetCoordinates2D()
if ALICE_PairIsFirstContact() then
data.lightning = AddLightning("CLPB", false, x1, y1, x2, y2)
else
MoveLightning(data.lightning, x1, y1, x2, y2)
end
elseif data.lightning then
DestroyLightning(data.lightning)
data.lightning = nil
end
end
function LightningChainOnBreak(__, __, data)
if data.lightning then
DestroyLightning(data.lightning)
data.lightning = nil
end
end
function LightningChain(unitA, unitB)
local data = ALICE_PairLoadData()
if ALICE_PairGetDistance2D < 500 then
local x1, y1, x2, y2 = ALICE_PairGetCoordinates2D()
if ALICE_PairIsFirstContact() then
data.lightning = AddLightning("CLPB", false, x1, y1, x2, y2)
else
MoveLightning(data.lightning, x1, y1, x2, y2)
end
elseif data.lightning then
DestroyLightning(data.lightning)
data.lightning = nil
end
end
ALICE_FuncSetOnBreak(LightningChain, LightningChainOnBreak)
function LightningChainOnReset(__, __, data)
DestroyLightning(data.lightning)
end
function LightningChain(unitA, unitB)
local data = ALICE_PairLoadData()
if ALICE_PairGetDistance2D < 500 then
local x1, y1, x2, y2 = ALICE_PairGetCoordinates2D()
if ALICE_PairIsFirstContact() then
data.lightning = AddLightning("CLPB", false, x1, y1, x2, y2)
else
MoveLightning(data.lightning, x1, y1, x2, y2)
end
else
ALICE_PairReset()
end
end
ALICE_FuncSetOnReset(LightningChain, LightningChainOnReset)
function FireDamage(fire, unit)
if not ALICE_PairIsEnemy() then
return 0.5
end
if ALICE_PairGetDistance2D() < 250 then
UnitDamageTarget(fire.source, unit, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
end
return 0.5
end
function FireDamage(fire, unit)
if not ALICE_PairIsEnemy() then
ALICE_PairDisable()
return 0.5
end
if ALICE_PairGetDistance2D() < 250 then
UnitDamageTarget(fire.source, unit, 25, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
end
return 0.5
end
ALICE_FuncSetInit(FireDamage, function()
if not ALICE_PairIsEnemy() then
ALICE_PairDisable()
end
end)
interactions = {
[{"unit", "flammable"}] = FireDamage,
[{"destructable", "flammable"}] = FireDamage
}
ALICE_AddIdentifier(object, "flammable")
ALICE_RemoveIdentifier(object, "flammable")
function FireDamage(fire, unit)
if fire.strength < 10 then
ALICE_PairPause()
return 0.5
end
if not ALICE_PairIsEnemy() then
ALICE_PairDisable()
return 0.5
end
if ALICE_PairGetDistance2D() < 250 then
UnitDamageTarget(fire.source, unit, 5*(fire.strength - 10), false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
end
return 0.5
end
if oldStrength < 10 and newStrength >= 10 then
ALICE_Unpause(fire, FireDamage)
end
local myAura = {
identifier = "aura",
anchor = myUnit
}
ALICE_Create(myAura)
ALICE_HasActor(myUnit, "unit") --true
ALICE_HasActor(myUnit, "aura") --true
ALICE_HasActor(myAura, "aura") --true
ALICE_HasActor(myAura, "unit") --false
if GetLocalPlayer() == whichPlayer then
ALICE_CallDelayed(function() BlzFrameSetVisible(whichFrame, false) end, 2.5)
end
ALICE_CallDelayed(function()
if GetLocalPlayer() == whichPlayer then
BlzFrameSetVisible(whichFrame, false)
end
end, 2.5)
Key | Description |
---|---|
CTRL + Q | Cycle through the different actors anchored to the selected host. |
CTRL + W | Lock selection so that clicking somewhere does not deselect the currently selected actor. |
CTRL + T | Halt the cycle. Hold SHIFT to pause all units. |
CTRL + R | Execute the next step of the cycle. |
CTRL + G | Toggle printing the function names of all invoked interaction functions for the selected actor. |
function InteractionFunc(objectA, objectB)
if not condition1 then
return
end
if not condition2 then
return
end
if not condition3 then
return
end
DoStuff(objectA, objectB)
end
function InteractionFunc(objectA, objectB)
objectA.failedCondition1 = nil
objectA.failedCondition2 = nil
objectA.failedCondition3 = nil
if not condition1 then
objectA.failedCondition1 = true
return
end
if not condition2 then
objectA.failedCondition2 = true
return
end
if not condition3 then
objectA.failedCondition3 = true
return
end
DoStuff(objectA, objectB)
end
ALICE_TrackVariables("failedCondition1", "failedCondition2", "failedCondition3")
FailedCondition1 = {}
FailedCondition2 = {}
FailedCondition3 = {}
function InteractionFunc(objectA, objectB)
--[...]
FailedCondition1[objectA] = true
--[...]
end
ALICE_TrackVariables("FailedCondition1", "FailedCondition2", "FailedCondition3")
{"unit" = DamageUnit, [{"unit", "hero"}] = DamageHero}
) is now supported.