Here is a more complete script I have come up with, grabbing some features from the other scripts of the thread.
I obviously use my improved SendingFormula function.
I added the concept of specifying a slow or fast casting time, slow being for the formulas that should as exact as possible, spellbooks spells come to mind here. The fast casting should succeed most of time, but 2 elements might be switched around from time to time.
I made it easier for people that want to customize their controls in Magicka (mouse buttons, space bar, shift key).
I added of bunch of combos, some of which might be obsolete now. I am not sure as I have not played a lot with it, I mainly tested if it was working or not.
Have fun!
Code:
#NoEnv
#SingleInstance force
Process,Priority,Magicka,High
Process,Priority,Magicka.exe,High
Process,Priority,,Realtime
SetKeyDelay, -1, -1
SetMouseDelay, -1
;Fix for Win7 with UAC
if not A_IsAdmin ;if code does not have admin rerun it with them
{
DllCall("shell32\ShellExecuteA", uint, 0, str, "RunAs", str, A_AhkPath
, str, """" . A_ScriptFullPath . """", str, A_WorkingDir, int, 1)
ExitApp
}
;other init
WinWait, Magicka,
IfWinNotActive, Magicka, , WinActivate, Magicka,
WinWaitActive, Magicka,
;Key Delays ;My suggested minimal values for the delays
pressDurationSlow=40 ;min 40
delayBetweenKeysSlow=40 ;min 40
delayBetweenPressesSlow=25 ;min 25
pressDurationFast=40 ;min 40
delayBetweenKeysFast=40 ;min 40
delayBetweenPressesFast=15 ;min 10
;Key bindings, change them to reflect your in game key bindings
basicCastKey = RButton ;Cast Force/Cast Area - RButton by default
selfCastKey = MButton ;Cast Self - MButton by default
spellCastKey = Space ;Boost/Cast magic - Space by default
modCastKey = LShift ;Shift - LShift by default
attackKey = LButton ;Move/Attack - LButton by default
;Cast Modes
basic = 1
self = 2
aoe = 3
imbue = 4
imbuse = 5 ;contraction for imbue and use
spell = 6
;Cast speeds
slow = true
fast = false
;Spellbook spells
Grease = qdw
Revive = wa
Haste = asf
MeteorShower = fdfqdf
Nullify = se
Rain = qqf
ThunderBolt = fqasa
Tornado = dqfqqf
Conflagration = fqffqffq
TimeWarp = re
Blizzard = rrqr
Teleport = asa
SummonPhoenix = waf
Thunderstorm = fqfqasa
RaiseDead = qrdsr
Fear = rse
Charm = wed
SummonDeath = srrqrs
SummonElemental = sedqfs
Corporealize = sqfaes
Invisibility = seqfs
Vortex = qrsqreqr
CrashDesktop = aafw
;beams & novas
ArcaneSteamLightning = qfqfaas
SuperSteamLightning = qfqfqfsa
superWetSteamLightning = qfqfqfsar
SteamElectricExplosion = qfsssa
ArcaneColdLigthning = rsasa
;barriers
SuperExplodingElectricIceWall = eqrqrsa
ExplosiveSlowingLigthningIcicles = qraser
StoneWall = edddd
LigthningIcicles = qreaaa
;mines
ARSEMines = arse
;storms
FrostLigthningStorm = erara
SteamLigthningStorm = qfqfeaa
;imbue
;general
WaterSurge = qqqqq
ArcaneWaterBall = qfsd
ArcaneColdBall = sdr
Waterquake = ddddq
Freezequake = ddddr
;projectiles
BlizzardBall = dqrqrqrqr
NeedleSpray = qrqrqrsa
;protect/heal
SuperSAFEResistAura = qfsafe
SuperDryAura = qfqfsaer
Heal = wwwww
HealingGlacierMines = qwer
Remedy = qwff
RemedyMines = qweff
; ************************ Hotkeys for magicks ****************************
;DomagickaSpell(formula, cast mode, speed of casting, "beam/charge key", after cast delay)
F1::DoMagickaSpell(Teleport,spell,slow,null,500)
F2::DoMagickaSpell(Haste,spell,slow,null)
;F3 see combos section for Bullet Time
F4::DoMagickaSpell(Invisibility,spell,slow,null)
F5::DoMagickaSpell(Charm,spell,slow,null)
F6::DoMagickaSpell(RaiseDead,spell,slow,null,700)
F7::DoMagickaSpell(SummonElemental,spell,slow,null,700)
F8::DoMagickaSpell(SummonDeath,spell,slow,null,700)
F9::DoMagickaSpell(Grease,spell,slow,null,1000)
F10::DoMagickaSpell(Conflagration,spell,slow,null,500)
F11::DoMagickaSpell(Tornado,spell,slow,null,900)
F12::DoMagickaSpell(Vortex,spell,slow,null,2750)
t::DoMagickaSpell(ThunderBolt,spell,slow,null,700)
y::DoMagickaSpell(Corporealize,spell,slow,null,500)
1::DoMagickaSpell(Heal,self,fast,null)
!1::DoMagickaSpell(HealingGlacierMines,aoe,fast,null)
2::DoMagickaSpell(Remedy,self,fast,null)
!2::DoMagickaSpell(RemedyMines,aoe,fast,null)
3::DoMagickaSpell(SuperSAFEResistAura,self,fast,null)
!3::DoMagickaSpell(SuperDryAura,self,fast,null)
4::DoMagickaSpell(StoneWall,basic,fast,null)
!4::DoMagickaSpell(StoneWall,aoe,fast,null)
5::DoMagickaSpell(LigthningIcicles,basic,fast,null)
!5::DoMagickaSpell(LigthningIcicles,imbuse,fast,null)
6::DoMagickaSpell(ExplosiveSlowingLigthningIcicles,basic,fast,null)
!6::DoMagickaSpell(ExplosiveSlowingLigthningIcicles,aoe,fast,null)
7::DoMagickaSpell(ExplosiveSlowingLigthningIcicles,imbuse,fast,null)
8::DoMagickaSpell(FrostLigthningStorm,basic,fast,null)
!8::DoMagickaSpell(FrostLigthningStorm,aoe,fast,null)
9::DoMagickaSpell(SteamLigthningStorm,basic,fast,null)
!9::DoMagickaSpell(SteamLigthningStorm,aoe,fast,null)
n::DoMagickaSpell(ARSEMines,basic,fast,null)
m::DoMagickaSpell(ARSEMines,aoe,fast,null)
; ******************* Hotkeys for combos of spells **********************
F3:: ;Bullet Time
DoMagickaSpell(TimeWarp,spell,slow,null,600)
DoMagickaSpell(Haste,spell,slow,null)
return
;AOE Storm + damage spam : click ALT-v, release ALT, keep pressing v
!v::DoMagickaSpell(FrostLigthningStorm,aoe,fast,null,100)
v::DoMagickaSpell(SteamElectricExplosion,aoe,fast,null)
z:: ;AOE Spammable Freeze
DoMagickaSpell(ArcaneWaterBall,aoe,fast,null,300)
DoMagickaSpell(ArcaneColdBall,aoe,fast,null,300)
return
!z:: ;AOE Knockdown-Wet-Freeze-Destroy
DoMagickaSpell(Waterquake,aoe,fast,null,300)
DoMagickaSpell(Freezequake,aoe,fast,null,300)
DoMagickaSpell(SteamElectricExplosion,aoe,fast,null,300)
return
^z:: ;Freeze All
DoMagickaSpell("qe",self,fast,null,100)
DoMagickaSpell(Rain,spell,slow,null,2750)
DoMagickaSpell("re",self,fast,null,100)
DoMagickaSpell(Blizzard,spell,slow,null)
return
; ************************** Hotkeys for Special Cases ************************
; This section contains hotkeys that have quirky behavior. Because I use the same letter (with modifiers)
; for several hotkeys, and all those cases rely on the user holding a beam or charging key, and because
; I do have a tendancy to not hold the modifiers keys while the beam/charging is occuring, I was running
; into the problem of having several hotkeys trying to fire at the same time. Thus this temporary disabling
; of hotkeys in some of the cases below.
; Also, Shield boosting related hotkeys.
c:: ;Freeze and Cook in Line
DoMagickaSpell(FrostLigthningStorm,imbuse,fast,null,300)
DoMagickaSpell(superWetSteamLightning,basic,fast,"c")
return
!c:: ;Freeze and Cook in Arc
Hotkey, c, off
DoMagickaSpell(FrostLigthningStorm,basic,fast,null,200)
DoMagickaSpell(superWetSteamLightning,basic,fast,"c")
Hotkey, c, on
return
;Variations of the Arcane Steam Ligthning Beams
x::DoMagickaSpell(ArcaneSteamLightning,basic,fast,"x")
^x::
Hotkey, x, off
DoMagickaSpell(superWetSteamLightning,basic,fast,"x")
Hotkey, x, on
return
!x::
Hotkey, x, off
DoMagickaSpell(ArcaneColdLigthning,basic,fast,"x")
Hotkey, x, on
return
;Ice Projectiles
b::DoMagickaSpell(BlizzardBall,basic,fast,"b")
!b::
Hotkey, b, off
DoMagickaSpell(NeedleSpray,basic,fast,"b")
Hotkey, b, on
return
;Shield related hotkeys
g:: ;Full Bubble Shield
DoMagickaSpell("e",aoe,fast,null,300)
;Simulate a bunch of Boost key clicks
Loop, 75
{
;Simulate a really fast Boost key click
SendSpellCastKeyDown()
Sleep,GetDelayBetweenPresses(false)
SendSpellCastKeyUp()
Sleep,GetDelayBetweenPresses(false)
}
return
h:: ;Boost shield
Loop
{
GetKeyState, state, h, P
if state = D ; The key is held down
{
;Simulate a really fast Boost key click
SendSpellCastKeyDown()
Sleep,GetDelayBetweenPresses(false)
SendSpellCastKeyUp()
Sleep,GetDelayBetweenPresses(false)
}
else ;key released
break
}
return
return
;end of auto-execute section
; ******************************** Main Functions ****************************
/*
DoMagickaSpell
Arguments:
formula: sequence of elements [sqf etc]
castmode: basic[or 1] = basic cast, self[or 2] = self cast, aoe[or 3] = aoe cast,
imbue[or 4] = imbue weapon, imbuse[or 5] = imbue weapon and use it, spell[or 6] = spellbook cast
bSlow: true=slower but precise casting, false=faster but imprecise casting. Use slow[true] for spellbook casts.
key: a key between double quotes , or null if no such key is needed
This is the hotkey used to trigger the event and holds the "casting" button until
your hotkey is released. This is important for channeled spells like beams
as well as charge-ups like rock or icy shotgun.
afterCastDelay: key delay after spell/effect has been invoked. Used to slow down casting when you want to spam multiple spells really fast.
*/
DoMagickaSpell(formula, castmode, bSlow, key, afterCastDelay = 25)
{
SendFormula(formula, bSlow)
if (castmode=1) ; Cast Force/Cast Area aka Basic
{
SendBasicCastKeyDown()
Keywait,%key%
Sleep,GetPressDuration(bSlow)
SendBasicCastKeyUp()
}
else if (castmode=2) ; Self Cast
{
SendSelfCastKeyDown()
Keywait,%key%
Sleep,GetPressDuration(bSlow)
SendSelfCastKeyUp()
}
else if (castmode=3) ; AOE cast
{
SendModCastKeyDown()
SendBasicCastKeyDown()
Keywait, %key%
Sleep,GetPressDuration(bSlow)
SendModCastKeyUp()
SendBasicCastKeyUp()
}
else if (castmode=4) ; Imbue Weapon
{
SendModCastKeyDown()
SendAttackKeyDown()
Sleep,GetPressDuration(bSlow)
SendModCastKeyUp()
SendAttackKeyUp()
}
else if (castmode=5) ; Imbue Weapon and Use it aka Imbuse
{
SendModCastKeyDown()
SendAttackKeyDown()
Sleep,GetPressDuration(bSlow)
SendModCastKeyUp()
SendAttackKeyUp()
Sleep,300
SendModCastKeyDown()
SendAttackKeyDown()
Sleep,GetPressDuration(bSlow)
SendModCastKeyUp()
SendAttackKeyUp()
}
else if (castmode=6) ; Spellbook Cast
{
SendSpellCastKeyDown()
Sleep,GetPressDuration(bSlow)
SendSpellCastKeyUp()
}
Sleep, afterCastDelay
}
SendFormula(formula, bSlow = true)
{
;This function performs an improved version of the Send function.
;We try to simulate users that press down several keys really fast, then release them all,
;and that then proceed to repeat those 2 steps until their entire formula has been entered in input
;We do the same thing in this function. We send as many "key down" events as we can. When we detect that we need to reuse
;a key that has already been pressed down, we send a batch of corresponding "key up" events that we accumulated so far.
;After that, we can then start a new cycle of sending a bunch of "key down" events, followed by a bunch of "key up" events and so on.
keyUpSequence=
Loop, parse, formula
{
;detect case where we are trying to press down a given key for the second time
if(InStr(keyUpSequence, A_LoopField ) <> 0)
{
;before sending a press down for a given key a second time, first send the "key up" events we accumulated so far
Sleep, GetPressDuration(bSlow)
SendKeyUpSequence(keyUpSequence, bSlow)
keyUpSequence=
Sleep, GetDelayBetweenKeys(bSlow)
}
;send key down event
Send, {%A_LoopField% Down}
keyUpSequence.= A_LoopField
Sleep, GetDelayBetweenPresses(bSlow)
}
;we finished going through the formula, send the last batch of "key up" events we accumulated
Sleep, GetPressDuration(bSlow)
SendKeyUpSequence(keyUpSequence, bSlow)
}
SendKeyUpSequence(keySeq, bSlow = true)
{
;iterate through our list of "key up" events and send them all
Loop, parse, keySeq
{
Send, {%A_LoopField% Up}
Sleep, GetDelayBetweenPresses(bSlow)
}
}
; **************************** Utility functions ******************************
SendBasicCastKeyDown() ;Cast Force/Cast Area - RButton by default
{
global basicCastKey
Send, {%basicCastKey% Down}
}
SendBasicCastKeyUp() ;Cast Force/Cast Area - RButton by default
{
global basicCastKey
Send, {%basicCastKey% Up}
}
SendSelfCastKeyDown() ;Cast Self - MButton by default
{
global selfCastKey
Send, {%selfCastKey% Down}
}
SendSelfCastKeyUp() ;Cast Self - MButton by default
{
global selfCastKey
Send, {%selfCastKey% Up}
}
SendSpellCastKeyDown() ;Boost/Cast magic - Space by default
{
global spellCastKey
Send, {%spellCastKey% Down}
}
SendSpellCastKeyUp() ;Boost/Cast magic - Space by default
{
global spellCastKey
Send, {%spellCastKey% Up}
}
SendModCastKeyDown() ;Shift - LShift by default
{
global modCastKey
Send, {%modCastKey% Down}
}
SendModCastKeyUp() ;Shift - LShift by default
{
global modCastKey
Send, {%modCastKey% Up}
}
SendAttackKeyDown() ;Move/Attack - LButton by default
{
global attackKey
Send, {%attackKey% Down}
}
SendAttackKeyUp() ;Move/Attack - LButton by default
{
global attackKey
Send, {%attackKey% Up}
}
GetPressDuration(bSlow = true)
{
global pressDurationSlow
global pressDurationFast
ifEqual, bSlow, true
{
return pressDurationSlow
}
else
{
return pressDurationFast
}
}
GetDelayBetweenKeys(bSlow = true)
{
global delayBetweenKeysSlow
global delayBetweenKeysFast
ifEqual, bSlow, true
{
return delayBetweenKeysSlow
}
else
{
return delayBetweenKeysFast
}
}
GetDelayBetweenPresses(bSlow = true)
{
global delayBetweenPressesSlow
global delayBetweenPressesFast
ifEqual, bSlow, true
{
return delayBetweenPressesSlow
}
else
{
return delayBetweenPressesFast
}
}