Code: Select all
| Click.mac v3.00b - Ressurrect corpses around you using cleric epic or spells
| by blueninja
|
| Features:
| Automatically ressurects corpses with in a specified radius around you. Chooses epic or appropriate
| spell automatically. Optionally consents corpses before rez to determine if the timer has expired.
| The order in which corpses are resurrected is determined by a set of rules determined in the
| ini file with a possibility to entirely avoid certain corpses. The availiable sort criteria are
| name, class, guild, ingroup, inraid, everyone and random.
| Swaps epic in and out automatically using Rusty's spell_routines.inc.
| Skips corpses whose owner is already looting it. Skips corpses acknowledged by other clerics (using
| hails or configurable phrases).
| Configurable messages sent to the owner of the corpse and configurable channel.
| Special guildlobby mode, only resurrect corpses whose owner is near them.
|
| Stealth features:
| Configurable random time delay between rezzes.
| Possibility to change the percentage of rez announcements (don't announce every corpse to hide
| how fast you are able to rez).
| Line of sight check, you can opt to only resurrect corpses that are visible to you.
| Random weight, allows you to randomly bypass the predefined sort order.
|
| Requirements:
| A cleric or paladin.
| Rusty's spell_routines.inc, found here:
| http://www.macroquest2.com/phpBB2/viewtopic.php?t=11656 (enhanced vip version by A_Druid_00)
| http://www.macroquest2.com/phpBB2/viewtopic.php?t=7568 (original non-vip version)
| A pile of dead people.
|
| Usage:
| click.mac [rad <radius>] [zradius <zradius>] [los/nolos] [ws <weightset>]
| [mw <minimumweight>] [lobby/nolobby]
| rad <radius> - sets the radius around in which to look for corpses
| zradius <zradius> - sets the vertical radius to look for corpses
| los / nolos - toggles the check for line of sight to corpses
| ws <weightset> - uses this key in the ini file to get sort keys
| mw <minimumweight> - the minimum weight value to rez a corpse, defaults to 0
| lobby/nolobby - toggles special guild lobby code on or off
|
| see example ini-file for a description of features.
#include spell_routines.inc
#define CL_INIFILE click.ini
#define REZ_SUCCESS 0
#define REZ_UNABLE 1
#define REZ_TOOOLD 2
#define REZ_SKIP 3
#define REZ_ERROR 4
#define GUILDLOBBYZONEID 344
#event ConHasTimer "This corpse's resurrection time will expire in#*#"
#event ConDecay "This corpse will decay in#*#"
#event ConTooOld "This corpse is too old to be resurrected."
#event ConTooOld "This corpse is waiting to expire."
#event UnableRez "You were unable to restore the corpse to life, but you may have success with a later attempt."
#include click_event.inc
Sub Event_UnableRez
/varset UnableReply 1
/return
Sub Event_Hail(string Line,string Hailer,string Hailee)
/declare cNum int local
/if (${NoiseLevel}>3) /echo Hail: ${Hailee} by ${Hailer}
/call FindExactPCID ${Hailer}
/if (${Spawn[corpse ${Hailee}].ID} && ${Spawn[id ${Macro.Return}].Class.Name.Equal[cleric]}) {
/if (${NoiseLevel}>2) /echo ${Hailee} rezzed by ${Hailer}. Added to skip list.
/varcalc SkipListSize ${SkipListSize}+1
/varset SkipList[${SkipListSize}] ${Hailee}
}
/return
Sub Event_ConTooOld
/varset GotConResponse 2
/return
Sub Event_ConHasTimer
/varset GotConResponse 1
/return
Sub Event_ConDecay
/varset GotCon 1
/return
Sub Main
/call CL_InitVars
/declare c int local 0
:checkparams
/if (${Defined[Param${c}]}) {
/if (${Param${c}.Equal[radius]}) {
/varset Radius ${Param${Math.Calc[${c}+1].Int}}
/varcalc c ${c}+2
} else /if (${Param${c}.Equal[zradius]}) {
/varset ZRadius ${Param${Math.Calc[${c}+1].Int}}
/varcalc c ${c}+2
} else /if (${Param${c}.Equal[los]}) {
/varset LOS 1
/varcalc c ${c}+1
} else /if (${Param${c}.Equal[nolos]}) {
/varset LOS 0
/varcalc c ${c}+1
} else /if (${Param${c}.Equal[ws]}) {
/varset WeightSet ${Param${Math.Calc[${c}+1].Int}}
/varcalc c ${c}+2
} else /if (${Param${c}.Equal[mw]}) {
/varset MinWeight ${Param${Math.Calc[${c}+1].Int}}
/varcalc c ${c}+2
} else /if (${Param${c}.Equal[lobby]}) {
/varset Lobby 1
/varcalc c ${c}+1
} else /if (${Param${c}.Equal[nolobby]}) {
/varset Lobby 0
/varcalc c ${c}+1
}
/if (${Defined[Param${c}]}) /goto :checkparams
}
/call ReadWeights ${WeightSet}
/call RezCorpses
/return
Sub TimeMS(int Seconds)
/return ${Math.Calc[${Seconds}\60].Int}m ${Math.Calc[${Seconds}%60].Int}s
/return
Sub RezCorpses
/declare c int local
/call BuildCorpseList
/if (!${CorpseListSize}) {
/if (${NoiseLevel}>0) /echo No corpses found within radius ${Radius}.
/return
}
/call _Array_Sort CorpseList CorpseWeights 1 ${CorpseListSize} 1
/declare tmpX1 int local
/declare tmpY1 int local
/declare tmpX2 int local
/declare tmpY2 int local
/varset c 0
/if (${Zone.ID}==GUILDLOBBYZONEID && ${Lobby}) {
/if (${NoiseLevel}>2) /echo In guild lobby. Only resurrecting players near their corpses.
}
/if (${NoiseLevel}>2) /echo Resurrecting with radius ${Radius}.
:rezloop
/varcalc c ${c}+1
/if (${c}>${CorpseListSize}) /goto :afterrezloop
/if (${Spawn[id ${CorpseList[${c}]} zradius ${ZRadius} radius ${Radius}].Deity.ID}) {
/call FindExactPCID ${Spawn[id ${CorpseList[${c}]}].CleanName.Arg[1,']}
/if (${Macro.Return}) {
/varset tmpX1 ${Spawn[id ${Macro.Return}].X}
/varset tmpY1 ${Spawn[id ${Macro.Return}].Y}
/varset tmpX2 ${Spawn[id ${CorpseList[${c}]}].X}
/varset tmpY2 ${Spawn[id ${CorpseList[${c}]}].Y}
/if (${Zone.ID}==GUILDLOBBYZONEID && ${Lobby}) {
/if (${Math.Distance[${tmpY1},${tmpX1}:${tmpY2},${tmpX2}]}<25 && ${Spawn[id ${Macro.Return}].Animation}==36) {
/if (${NoiseLevel}>2) /echo ${Spawn[id ${CorpseList[${c}]}].CleanName} skipped because owner is already looting.
/varcalc LootSkips ${LootSkips}+1
/goto :rezloop
} else /if (${Math.Distance[${tmpY1},${tmpX1}:${tmpY2},${tmpX2}]}>75) {
/if (${NoiseLevel}>2) /echo ${Spawn[id ${CorpseList[${c}]}].CleanName} skipped because zone is guildlobby and owner not near corpse.
/goto :rezloop
}
} else {
/if (${Math.Distance[${tmpY1},${tmpX1}:${tmpY2},${tmpX2}]}<25 && ${Spawn[id ${Macro.Return}].Animation}==36) {
/if (${NoiseLevel}>2) /echo ${Spawn[id ${CorpseList[${c}]}].CleanName} skipped because owner is already looting.
/varcalc LootSkips ${LootSkips}+1
/goto :rezloop
}
}
} else /if (${Zone.ID}==GUILDLOBBYZONEID && ${Lobby}) {
/goto :rezloop
}
/if (${c}>1) {
/delay ${Math.Rand[${RandomDelay}]}
}
/doevents
/call FindSkip ${Spawn[id ${CorpseList[${c}]}].CleanName.Arg[1,']}
/if (${Macro.Return}) {
/if (${NoiseLevel}>2) /echo ${Spawn[id ${CorpseList[${c}]}].CleanName.Arg[1,']} found in skip list. Ignoring.
/varcalc ListSkips ${ListSkips}+1
/goto :rezloop
}
/call RezID ${CorpseList[${c}]}
/if (${Macro.Return.Equal[REZ_SUCCESS]}) {
/if (${NoiseLevel}>3) /echo Successful: ${Spawn[id ${CorpseList[${c}]}].Name}.
/varcalc Successful ${Successful}+1
} else /if (${Macro.Return.Equal[REZ_UNABLE]}) {
/if (${NoiseLevel}>3) /echo Unable to restore: ${Spawn[id ${CorpseList[${c}]}].Name}.
/varcalc Unable ${Unable}+1
} else /if (${Macro.Return.Equal[REZ_TOOOLD]}) {
/if (${NoiseLevel}>3) /echo Too old: ${Spawn[id ${CorpseList[${c}]}].Name}.
/varcalc TooOld ${TooOld}+1
} else /if (${Macro.Return.Equal[REZ_ERROR]}) {
/varcalc RezError ${RezError}+1
}
}
/goto :rezloop
:afterrezloop
/if (${NoiseLevel}>2) /call ShowStats
/if (${OldPrimary.NotEqual[${InvSlot[mainhand].Item.Name}]}) {
/call EquipItem "${OldPrimary}|mainhand"
}
/return
Sub RezID(int ID)
/target id ${ID}
/if (${ConCorpse}) {
/doevents Hail
/doevents flush
/consider
/varset GotCon 0
/varset GotConResponse 0
/varset ConTimeout 100
:waitcon
/doevents
/if (!${GotCon} && ${ConTimeout}) /goto :waitcon
/doevents
/if (${GotConResponse}==2) /return REZ_TOOOLD
}
:rezcorpse
/if (${UseEpic}) {
/if (${InvSlot[mainhand].Item.Name.NotEqual[Water Sprinkler of Nem Ankh]}) {
/call EquipItem "Water Sprinkler of Nem Ankh|mainhand"
}
/call AnnounceRez
/call Cast "Water Sprinkler of Nem Ankh" item
} else {
:waitmana
/if (${Me.CurrentMana}>${Math.Calc[${Spell[${RezSpell}].Mana}*1.2]}) {
/if (!${Me.Standing}) /stand
/call AnnounceRez
/call Cast "${RezSpell}" gem${SpellGem} 30s
} else {
/if (!${Me.Sitting} || !${Me.Mount.ID}) /sit
/delay 30
/goto :waitmana
}
}
/if (${Macro.Return.Equal[CAST_SUCCESS]}) {
/varset UnableTimer 25
/varset UnableReply 0
:waitunable
/doevents UnableRez
/if (${UnableTimer} && !${UnableReply}) /goto :waitunable
/if (!${UnableReply}) /return REZ_SUCCESS
/return REZ_UNABLE
} else /if (${Macro.Return.Equal[CAST_CANCELLED]}) {
/return REZ_SKIP
} else /if (${Macro.Return.Equal[CAST_INTERRUPTED]} || ${Macro.Return.Equal[CAST_NOTREADY]}) {
/goto :rezcorpse
}
/return REZ_ERROR
Sub AnnounceRez
/if (${NoiseLevel}>2) /echo Resurrecting ${Target.Name}
/if (${Math.Rand[100]}<${AnnouncePct}) {
/if (${AnnounceChan.NotEqual[0]}) /${AnnounceChan} ${AnnounceMsg}
/if (${AnnounceHail}) /keypress hail
}
/if (${SendTell}) /tell ${Target.CleanName.Arg[1,']} ${Tell}
/return
Sub CL_InitVars
/declare NoiseLevel int outer ${Ini[CL_INIFILE,Main,NoiseLevel,2]}
/if (${NoiseLevel}>1) /echo Click.mac v3.00b - by blueninja
/declare ConTimeout timer outer
/declare CorpseList[200] int outer 0
/declare CorpseWeights[200] int outer 0
/declare CorpseListSize int outer 0
/declare CurrentCorpse int outer
/declare SkipListSize int outer 0
/declare SkipList[50] string outer
/declare MinWeight int outer 0
/declare WeightSet string outer Weights
/declare UnableTimer timer outer
/declare UnableReply bool outer
/declare Radius int outer ${Ini[CL_INIFILE,Main,Radius,200]}
/declare ZRadius int outer ${Ini[CL_INIFILE,Main,ZRadius,100]}
/declare LOS bool outer ${Ini[CL_INIFILE,Main,LineOfSight,1]}
/declare Lobby bool outer ${Ini[CL_INIFILE,Main,Lobby,1]}
/declare Tell string outer ${Ini[CL_INIFILE,Main,Tell,Inc Rez!!]}
/declare SendTell bool outer ${Ini[CL_INIFILE,Main,SendTell,0]}
/declare AnnounceChan string outer ${Ini[CL_INIFILE,Main,AnnounceChan,0]}
/declare AnnouncePct int outer ${Ini[CL_INIFILE,Main,AnnouncePct,0]}
/declare AnnounceMsg string outer ${Ini[CL_INIFILE,Main,AnnounceMsg,Rezzing %t !]}
/declare AnnounceHail bool outer ${Ini[CL_INIFILE,Main,AnnounceHail,0]}
/declare RandomDelay int outer ${Ini[CL_INIFILE,Main,RandomDelay,0]}
/declare Successful int outer 0
/declare Unable int outer 0
/declare TooOld int outer 0
/declare RezError int outer 0
/declare BlackList int outer 0
/declare ListSkips int outer 0
/declare LootSkips int outer 0
/declare GotCon int outer
/declare GotConResponse int outer
/declare ConCorpse int outer 1
/declare OldPrimary string outer ${InvSlot[mainhand].Item.Name}
/declare SpellGem int outer ${Ini[CL_INIFILE,Main,SpellGem,8]}
/declare RezSpell string outer
/declare UseEpic bool outer ${FindItem[=Water Sprinkler of Nem Ankh].ID}
/if (!${UseEpic}) {
/if (${Me.Book[Reviviscence]}) {
/varset RezSpell Reviviscence
} else /if (${Me.Book[Resurrection]}) {
/varset RezSpell Resurrection
} else /if (${Me.Book[Restoration]}) {
/varset RezSpell Restoration
} else /if (${Me.Book[Resuscitate]}) {
/varset RezSpell Resuscitate
} else /if (${Me.Book[Renewal]}) {
/varset RezSpell Renewal
} else /if (${Me.Book[Reparation]}) {
/varset RezSpell Reparation
} else /if (${Me.Book[Reconstitution]}) {
/varset RezSpell Reconstitution
} else /if (${Me.Book[Reanimation]}) {
/varset RezSpell Reanimation
} else {
/if (${NoiseLevel}>0) /echo ERROR: Couldn't find resurrection spell or epic!
/end
}
/if (${NoiseLevel}>2) /echo Epic not found. Using spell ${RezSpell}.
} else {
/if (${NoiseLevel}>2) /echo Epic found.
}
/declare Weights[200] string outer
/declare WeightCount int outer 0
/return
Sub ReadWeights(string WSection)
/declare c int local
/declare sTmp string ${Ini[CL_INIFILE,${WSection}]}
/if (${Math.Calc[${sTmp.Count[|]}-1]}) {
/varset WeightCount ${Math.Calc[${sTmp.Count[|]}-1]}
/for c 1 to ${WeightCount}
/varset Weights[${c}] ${Ini[CL_INIFILE,${WSection},${sTmp.Arg[${c},|]}]}
/next c
}
/return
Sub ShowStats
/echo ---------------------------------------
/echo Successful resurrections: ${Successful},
/echo Unable to restore: ${Unable}, TooOld: ${TooOld}${If[${RezError}, Errors: ${RezError},]}.
/echo Skipped due to looting: ${LootSkips}, due to hails: ${ListSkips},
/echo due to negative weights: ${BlackList}.
/call TimeMS ${Macro.RunTime}
/echo Total corpses: ${CorpseListSize}. Total runtime: ${Macro.Return}
/echo ---------------------------------------
/return
Sub FindSkip(string Name)
/if (!${SkipListSize}) /return 0
/declare c int local
/for c 1 to ${SkipListSize}
/if (${SkipList[${c}].Equal[${Name}]}) /return ${c}
/next c
/return 0
Sub RemoveCorpse(int num)
|Kolla om tom
/declare c int local
/for c ${num} to ${CorpseListSize}
/varset CorpseList[${c}] ${CorpseList[${Math.Calc[${c}+1]}]}
/next c
/varset CorpseList[${CorpseListSize}] 0
/varcalc CorpseListSize ${CorpseListSize}-1
/return
Sub BuildCorpseList
/declare c int local
/declare cID int local
/declare wTmp int local
/varset CorpseListSize 0
/if (!${SpawnCount[corpse zradius ${ZRadius} radius ${Radius}]}) /return
/for c 1 to ${SpawnCount[corpse zradius ${ZRadius} radius ${Radius}]}
/varset cID ${NearestSpawn[${c},zradius ${ZRadius} corpse radius ${Radius}].ID}
/if (${Spawn[id ${cID}].Deity.ID} && ((${LOS} && ${Spawn[id ${cID}].LineOfSight}) || !${LOS})) {
/call GetCWeight ${cID}
/if (${NoiseLevel}>3) /echo ${Spawn[id ${cID}].Name} (${Spawn[id ${cID}].Class.Name}) wt: ${Macro.Return}
/varset wTmp ${Macro.Return}
/if (${wTmp}<${MinWeight}) {
/varcalc BlackList ${BlackList}+1
/next c
}
/varcalc CorpseListSize ${CorpseListSize}+1
/varset CorpseList[${CorpseListSize}] ${cID}
/varset CorpseWeights[${CorpseListSize}] ${wTmp}
}
/next c
/return
Sub GetCWeight(int ID)
/if (!${WeightCount}) /return 0
/declare c int local
/declare d int local
/declare wTmp int local 0
/declare wType string local
/declare wNot bool local
/for c 1 to ${WeightCount}
/varset wType ${Weights[${c}].Arg[1,|]}
/varset wNot ${wType.Left[1].Equal[!]}
/if (${wNot}) /varset wType ${wType.Right[${Math.Calc[${wType.Length}-1]}]}
/if (${wType.Equal[name]}) {
/if (${wNot} ^^ ${Spawn[id ${ID}].CleanName.Arg[3,|].Equal[${Weights[${c}].Arg[3,|]}]}) /varcalc wTmp ${wTmp}+${Weights[${c}].Arg[2,|]}
} else /if (${wType.Equal[guild]}) {
/if (${Spawn[id ${ID}].Guild.Length}) {
/if (${wNot} ^^ ${Spawn[id ${ID}].Guild.Equal[${Weights[${c}].Arg[3,|]}]}) /varcalc wTmp ${wTmp}+${Weights[${c}].Arg[2,|]}
} else {
/call FindExactPCID ${Spawn[id ${ID}].CleanName.Arg[3,']}
/if (${Macro.Return}) {
/if (${wNot} ^^ ${Spawn[id ${Macro.Return}].Guild.Equal[${Weights[${c}].Arg[3,|]}]}) /varcalc wTmp ${wTmp}+${Weights[${c}].Arg[2,|]}
} else {
/if (${wNot}) /varcalc wTmp ${wTmp}+${Weights[${c}].Arg[2,|]}
}
}
} else /if (${wType.Equal[class]}) {
/if (${wNot} ^^ ${Spawn[id ${ID}].Class.Name.Equal[${Weights[${c}].Arg[3,|]}]}) /varcalc wTmp ${wTmp}+${Weights[${c}].Arg[2,|]}
} else /if (${wType.Equal[ingroup]}) {
/if (${wNot} ^^ (${Group.Members} && ${Group.Member[${Spawn[id ${ID}].CleanName.Arg[3,']}]})) /varcalc wTmp ${wTmp}+${Weights[${c}].Arg[2,|]}
} else /if (${wType.Equal[inraid]}) {
/if (${wNot} ^^ ${Raid.Member[${Spawn[id ${ID}].CleanName.Arg[3,']}].Level}) /varcalc wTmp ${wTmp}+${Weights[${c}].Arg[2,|]}
} else /if (${wType.Equal[random]}) {
/if (${wNot} ^^ ${Weights[${c}].Arg[3,|]}<${Math.Rand[100]}) /varcalc wTmp ${wTmp}+${Weights[${c}].Arg[2,|]}
} else /if (${wType.Equal[everyone]}) {
/if (!${wNot}) /varcalc wTmp ${wTmp}+${Weights[${c}].Arg[2,|]}
}
/next c
/return ${wTmp}
Sub FindExactPCID(string Name)
/declare CurrentID int local
/declare FirstID int local
/declare Counter int local 1
/varset CurrentID ${Spawn[pc ${Name}].ID}
:FESI_FindNext
/if (!${CurrentID} || ${Spawn[id ${CurrentID}].CleanName.Equal[${Name}]}) /return ${CurrentID}
/varset CurrentID ${Spawn[id ${Me.ID}].NearestSpawn[${Counter},pc ${Name}].ID}
/varcalc Counter ${Counter}+1
/goto :FESI_FindNext
/return 0
Sub _Array_Sort(string Array,string ArrayW,Lo,Hi,D)
/declare L int local ${Lo}
/declare R int local ${Hi}
/declare P int local ${Math.Calc[(${Lo}+${Hi})\2]}
:while1
/if (${L}<${R}) {
:while2
/if (${Math.Calc[${${ArrayW}[${P}]}-${${ArrayW}[${L}]}]}>0) {
/varcalc L ${L}+1
/goto :while2
}
:while3
/if (${Math.Calc[${${ArrayW}[${P}]}-${${ArrayW}[${R}]}]}<0) {
/varcalc R ${R}-1
/goto :while3
}
/if (${L}<=${R}) {
/call _Array_Swap ${Array} ${ArrayW} ${L} ${R} ${D}
/varcalc L ${L}+1
/varcalc R ${R}-1
}
/goto :while1
}
/if (${Lo}<${R}) /call _Array_Sort ${Array} ${ArrayW} ${Lo} ${R} ${D}
/if (${L}<${Hi}) /call _Array_Sort ${Array} ${ArrayW} ${L} ${Hi} ${D}
/return
Sub _Array_Swap(string Array,string ArrayW,int Lo,int Hi,int D)
/declare S string local ${${Array}[${Lo}]}
/declare W string local ${${ArrayW}[${Lo}]}
/varset ${Array}[${Lo}] ${${Array}[${Hi}]}
/varset ${Array}[${Hi}] ${S}
/varset ${ArrayW}[${Lo}] ${${ArrayW}[${Hi}]}
/varset ${ArrayW}[${Hi}] ${W}
/return