Advertisement
Guest User

AzzyUtil.lua

a guest
Mar 22nd, 2018
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 69.19 KB | None | 0 0
  1. -------------------------------
  2. -- This file is part of AzzyAI 1.55
  3. -- If you want to use these functions in your own AI
  4. -- it is reccomended that you use the seperately available
  5. -- version, which does not utilize AAI-specific systems.
  6. -- Written by Dr. Azzy of iRO Chaos
  7. AUVersion="1.550"
  8. -------------------------------
  9.  
  10.  
  11.  
  12.  
  13. --[[
  14. USAGE NOTES
  15.  
  16.  
  17. HPPercent(id)
  18. SPPercent(id)
  19. Returns the current hp or sp of id as a percentage. This only works on things which the player can see the hp/sp of, obviously.
  20.  
  21. Closer(id,x,y)
  22. Returns coordinants of a location 1 cell closer to actor (id)
  23.  
  24. ClosestR(id1,id2,range)
  25. Returns coordinants of the cell within <range> cells of <id2> that is closest to <id1>.
  26. Intended for targeting of ranged skills.
  27.  
  28. BetterMoveToOwner(mercid,range)
  29. Moves to the closest sell withing range cells of the owner.
  30.  
  31. IsNotKS(id)
  32. Returns 1 if attacking monster (id) would be a KS, 0 otherwise.
  33.  
  34. IsFriend(id)
  35. Returns 1 if (id) is the owner or a friend.
  36.  
  37. @@@@@@@@@@@@@@@@@@@@@@@@@
  38. @@@ Monster Functions @@@
  39. @@@@@@@@@@@@@@@@@@@@@@@@@
  40.  
  41. GetMobCount(id,range,[id2])
  42. Returns the number of monsters within range cells of the actor id, and the number of said monsters which are currently targeting id. If id2 is specified, monsters which are targeting id2 will also be included in the second value returned.
  43. Useful for deciding whether to use anti-mob skills.
  44. ex:
  45. local mobcount,aggrocount = GetMobCount(MyID,1,GetV(V_OWNER,MyID))
  46.  
  47. GetBestBrandishTarget(id)
  48. Returns the id of the best monster adjacent to the mercenary to use brandish spear on (that is, the target that will result in the most monsters being hit).
  49. Assumes level 1 brandish area.
  50.  
  51. ex:
  52. SkillObject(MyID,MySkillLevel,ML_BRANDISH,GetBestBrandishTarget(MyID))
  53.  
  54.  
  55. @@@@@@@@@@@@@@@@@@@@@@@
  56. @@@ Skill Functions @@@
  57. @@@@@@@@@@@@@@@@@@@@@@@
  58.  
  59. GetAtkSkill(id)
  60. Returns a list containing skill id, skill level of the mercenary's single target offencive skill. Crash is not returned in this list, because the damage output spamming crash is lower than the damage output from using normal attacks.
  61.  
  62. ex:
  63. local skill,level= GetAtkSkill(MyID)
  64.  
  65. GetMobSkill(merctype)
  66. As GetAtkSkill() only for antimob skills
  67.  
  68. ex
  69. local skill,level = GetMobSkill(MyID)
  70.  
  71. GetQuickenSkill(id)
  72. Returns a list containing the ID of the weapon quicken skill posessed by the mercenary and the skill level
  73.  
  74. ex
  75. local skill,level = GetQuickenSkill(MyID)
  76.  
  77. GetGuardSkill(id)
  78. As GetQuickenSkill() only returns the ID of the guard or parry skill posessed by the mercenary.
  79.  
  80. GetSacrificeSkill(id)
  81. As GetQuickenSkill() only returns the ID and other perameters for the Sacrifice (aka Devotion) skill posessed by the mercenary.
  82.  
  83. GetProvokeSkill(id)
  84. As GetQuiceknSkill() only returns the ID and other perameters for the Provoke skill posessed by the mercenary.
  85.  
  86. GetPushbackSkill(id)
  87. As GetMobSkill() only returns the ID and other perameters for the pushback skill (arrow repel or skid trap) posessed by the mercenary
  88.  
  89. --]]--
  90.  
  91.  
  92. --#########################
  93. --### Tactics Functions ###
  94. --#########################
  95.  
  96. function GetTact(t,m)
  97. local x
  98. if m==nil then
  99. TraceAI("GetTact: Error - nil target")
  100. logappend("AAI_ERROR","GetTact: Error - nil target")
  101. end
  102. if t==nil then
  103. TraceAI("GetTact: Error - nil tactic target:"..m)
  104. logappend("AAI_ERROR","request for tactic type nil target:"..m)
  105. end
  106. if (IsPlayer(m)==1) then
  107. if (PVPmode~=0) then
  108. TraceAI("GetTact: Returning pvp tactic")
  109. return GetPVPTact(t,m)
  110. else
  111. TraceAI("GetTact: not pvp mode returning 0")
  112. return 0
  113. end
  114. end
  115. local e = 0
  116. if (IsHomun(MyID)==0) then
  117. if (MobID[m]==nil) then
  118. e=GetClass(m)
  119. else
  120. e=MobID[m]
  121. end
  122. else
  123. e=GetV(V_HOMUNTYPE,m)
  124. end
  125. temp=GetMyTact(e)
  126. if (temp==nil) then
  127. if (e >= 1324 and e <= 1363) or (e >= 1938 and e <=1946) then
  128. temp=GetMyTact(13)
  129. TraceAI("GetTact: No tactic "..t.." for "..e.."actor: "..m.." but it's a treasure chest.")
  130. end
  131. if temp==nil then
  132. temp=GetMyTact(0)
  133. --TraceAI("GetTact: No tactic "..t.." for "..e.."actor: "..m.." using default instead")
  134. end
  135. end
  136. if (temp[t]==nil) then
  137. temp=GetMyTact(0)
  138. TraceAI("GetTact: Undefined tactic "..t.." for "..e.."actor: "..m.." using default instead")
  139. end
  140. x=temp[t]
  141. if (x==nil) then
  142. logappend("AAI_ERROR","Default tactic "..t.." is undefined - Please review and correct tactics file or restore default tactics file")
  143. return 0
  144. else
  145. if t==TACT_SP and x==-1 then
  146. x = AttackSkillReserveSP
  147. elseif t==TACT_CHASE then
  148. --TraceAI("TactChase called"..GetV(V_SP,MyID).." "..ChaseSPPauseSP.." "..GetTick().." "..math.max(LastMovedTime,LastSPTime).." "..(5000-ChaseSPPauseTime))
  149. if GetV(V_SP,MyID) < ChaseSPPauseSP and (GetTick() - math.max(LastMovedTime,LastSPTime)) > (5000-ChaseSPPauseTime) then
  150. if ((ChaseSPPause==1 and x~=CHASE_ALWAYS) or x==CHASE_CLEVER) then
  151. TraceAI("Cleverchase activated: "..m.." ("..e..") ".." LastTick "..math.max(LastMovedTime,LastSPTime))
  152. return 1
  153. end
  154. end
  155. if x==CHASE_ALWAYS then
  156. return 0
  157. elseif x==CHASE_NEVER then
  158. return 1
  159. else
  160. return DoNotChase
  161. end
  162. end
  163. return x
  164. end
  165. end
  166.  
  167. function GetMyTact(m)
  168. return MyTact[m]
  169. end
  170.  
  171. function GetPVPTact(t,m)
  172. local x
  173. local class
  174. local e = ENEMY
  175. if IsMonster(m)==0 then
  176. TraceAI("pvp tact lookup on ally")
  177. e= ALLY
  178. end
  179. if (MyPVPTact[m]~=nil) then
  180. e = m
  181. elseif (MyFriends[m]~=nil) then
  182. e = MyFriends[m]
  183. end
  184. if IsHomun(MyID)==1 then
  185. class=GetV(V_HOMUNTYPE,m)
  186. end
  187. if MyPVPTact[m]~=nil then
  188. x=MyPVPTact[m][t]
  189. elseif e~=ALLY and class~=nil then
  190. if MyPVPTact[class] ~=nil then
  191. x=MyPVPTact[class][t]
  192. end
  193. elseif MyFriends[e]==nil then
  194. x=MyPVPTact[e][t]
  195. end
  196. if x==nil then
  197. x=MyPVPTact[0][t]
  198. end
  199. if (x==nil) then
  200. TraceAI("ERROR: Default PVP tactic "..t.." is undefined!")
  201. logappend("AAI_ERROR","Default PVP tactic "..t.." is undefined! Please correct your PVP tactics file")
  202. return 0
  203. else
  204. TraceAI("pvp TL on P "..m.."IsMonster "..IsMonster(m).." type "..e.." for tactic "..t.." returning "..x)
  205. return x
  206. end
  207. end
  208.  
  209. function GetClass(m)
  210. if (m < MagicNumber) then
  211. return 10
  212. elseif (IsActive[m]==0 and AutoDetectPlant==1) then
  213. return 11
  214. else
  215. return 0
  216. end
  217. end
  218.  
  219. function IsRescueTarget(id)
  220. local tactrescue=GetTact(TACT_RESCUE,id)
  221. local target=GetV(V_TARGET,id)
  222. local owner=GetV(V_OWNER,MyID)
  223. if target==owner then
  224. local hp = HPPercent(owner)
  225. if RescueOwnerLowHP > hp then
  226. TraceAI("RescueOwnerLowHP -> rescue owner from "..id)
  227. return 1
  228. elseif RescueOwnerLowHP < 0 and -1*RescueOwnerLowHP < hp then
  229. TraceAI("RescueOwnerLowHP -> rescue of owner canceled "..id)
  230. return 0
  231. end
  232. end
  233. if tactrescue==RESCUE_NEVER then
  234. return 0
  235. else
  236. TraceAI("tactrescue not never "..tactrescue.." id "..id)
  237. if tactrescue==RESCUE_RETAINER then
  238. if MyFriends[target]==2 then
  239. return 1
  240. end
  241. elseif tactrescue==RESCUE_FRIEND then
  242. if MyFriends[target]==1 then
  243. return 1
  244. end
  245. elseif tactrescue==RESCUE_ALL then
  246. if IsFriendOrSelf(target)==1 and target ~=MyID then
  247. return 1
  248. end
  249. elseif tactrescue==RESCUE_OWNER then
  250. if target==GetV(V_OWNER,MyID) then
  251. return 1
  252. end
  253. elseif tactrescue==RESCUE_SELF then
  254. if target==MyID then
  255. return 1
  256. end
  257. end
  258. end
  259. return 0
  260. end
  261.  
  262. function GetTargetClass(id)
  263. -- 0 = no target, 1 = self 2= friend, -1 = other monster -2 = other player
  264. if id == MyID then
  265. return 1
  266. elseif id == 0 then
  267. return 0
  268. elseif (id > MagicNumber2) then
  269. if IsFriendOrSelf(id)==1 then
  270. return 2
  271. else
  272. return -2
  273. end
  274. elseif IsMonster(id)==1 then
  275. return -1
  276. else
  277. return 0
  278. end
  279. end
  280.  
  281. --########################
  282. --### Friend Functions ###
  283. --########################
  284.  
  285.  
  286. function IsFriend(id)
  287. if (id==GetV(V_OWNER,MyID)) then
  288. return 1
  289. elseif (id~= MyID) then
  290. friendclass=MyFriends[id]
  291. if (friendclass==FRIEND or friendclass==RETAINER) then
  292. return 1
  293. end
  294. end
  295. return 0
  296. end
  297.  
  298. function IsPVPFriend(id)
  299. if (id==GetV(V_OWNER,MyID)) then
  300. return 1
  301. elseif (id~= MyID) then
  302. friendclass=MyFriends[id]
  303. if (friendclass==FRIEND or friendclass==RETAINER or friendclass==NEUTRAL or friendclass==ALLY or friendclass==NEUTRAL) then
  304. return 1
  305. end
  306. end
  307. return 0
  308. end
  309.  
  310. function IsFriendOrSelf(id)
  311. if (id==GetV(V_OWNER,MyID) or id == MyID) then
  312. return 1
  313. else
  314. if (MyFriends[id]~=nil) then
  315. return 1
  316. end
  317. end
  318. return 0
  319. end
  320.  
  321. function IsPlayer(id)
  322. if (id>MagicNumber2) then
  323. return 1
  324. else
  325. return 0
  326. end
  327. end
  328.  
  329. function UpdateFriends()
  330. FriendsFile = io.open("AI/USER_AI/A_Friends.lua", "w")
  331. if FriendsFile~=nil then
  332. FriendsFile:write (STRING_A_FRIENDS_HEAD)
  333. for k,v in pairs(MyFriends) do
  334. if (v==FRIEND or (v==PKFRIEND and PainkillerFriendsSave == 1)) then
  335. FriendsFile:write ("MyFriends["..k.."]="..v.." -- \n")
  336. end
  337. end
  338. FriendsFile:close()
  339. else
  340. TraceAI("Failed to open A_Friends.lua for writing!")
  341. logappend("AAI_ERROR","Failed to open A_Friends.lua for writing!")
  342. end
  343. end
  344.  
  345. --########################
  346. --### Monster functions###
  347. --########################
  348.  
  349.  
  350. function GetAggroCount(target)
  351. local aggrocount=0
  352. if target ==nil then
  353. for k,v in pairs(Targets) do
  354. if v[2] > 0 then -- it's aggressive
  355. distance = GetDistanceA(GetV(V_OWNER,MyID),k)
  356. if (distance <= GetMoveBounds()) then
  357. aggrocount=aggrocount+1*GetTact(TACT_WEIGHT,k)
  358. end
  359. end
  360. end
  361. else
  362. for k,v in pairs(Targets) do
  363. if GetV(V_TARGET,k)==target then
  364. aggrocount=aggrocount+1*GetTact(TACT_WEIGHT,k)
  365. end
  366. end
  367. end
  368. return aggrocount
  369. end
  370.  
  371. function GetMobCount(skill,level,target,aggro)
  372. local mobcount=0
  373. if skill==0 or level==0 then
  374. return 0
  375. end
  376. local skillaoe=SkillAOEInfo[skill][1][level]
  377. local x,y=GetV(V_POSITION,MyID)
  378. if skillaoe==nil then
  379. if skill == ML_BRANDISH then
  380. for k,v in pairs (Targets) do
  381. if GetV(V_MOTION,k)~=MOTION_DEAD then
  382. if (GetDistanceA(myid,k)<=1 and GetDistanceA(target,k) <=1 and (v[2]>0 or aggro~=0)) then
  383. mobcount=mobcount+1*GetTact(TACT_WEIGHT,k)
  384. elseif (GetDistanceA(myid,k) ==2 and GetDistance3(myid,k) < 2.5 and GetDistance3(target,k) < 2.5 and (v[2]>0 or aggro~=0)) then -- sides, 2 cells to either side of target/merc
  385. mobcount=mobcount+1*GetTact(TACT_WEIGHT,k)
  386. end
  387. end
  388. end
  389. elseif skill== MA_SHARPSHOOTING then
  390. mx,my=GetV(V_POSITION,target)
  391. dx=math.abs(x-mx)
  392. dy=math.abs(y-my)
  393. if ((dx==0) or (dx==1 and dy>1) or (dx==2 and dy>6) or (dx==3 and dy>9) or (dx==4 and dy>11)) then
  394. if my>y then
  395. mobcount=GetFASTargetCount(MyID,0,1,aggro)
  396. elseif my<y then
  397. mobcount=GetFASTargetCount(MyID,0,-1,aggro)
  398. end
  399. elseif ((dy==0) or (dy==1 and dx>1) or (dy==2 and dx>6) or (dy==3 and dx>9) or (dy==4 and dx>11)) then
  400. if mx>x then
  401. mobcount=GetFASTargetCount(MyID,1,0,aggro)
  402. elseif mx<x then
  403. mobcount=GetFASTargetCount(MyID,-1,0,aggro)
  404. end
  405. -- diagonals
  406. elseif mx>x then
  407. if my>y then
  408. mobcount=GetFASTargetCount(MyID,1,1,aggro)
  409. else
  410. mobcount=GetFASTargetCount(MyID,-1,1,aggro)
  411. end
  412. elseif my>y then
  413. mobcount=GetFASTargetCount(MyID,1,-1,aggro)
  414. else
  415. mobcount=GetFASTargetCount(MyID,-1,-1,aggro)
  416. end
  417. end
  418. else -- we have a wellbehaved skill
  419. if GetSkillInfo(skill,7)==0 then
  420. target=MyID
  421. end
  422. range=(skillaoe-1)/2
  423. local logstring=""
  424. for k,v in pairs(Targets) do
  425. local tbas=GetTact(TACT_BASIC,k)
  426. local dist = GetDistanceAR(target,k)
  427. logstring=logstring.."|"..k.."v[2]"..v[2].."t"..GetV(V_TARGET,k).."m"..GetV(V_MOTION,k).."aggro"..aggro
  428. if dist <= range and (v[2]>0 or aggro~=0) and tbas~=0 then
  429. mobcount=mobcount+1*GetTact(TACT_WEIGHT,k)
  430. logstring=logstring.."add:"..GetTact(TACT_WEIGHT,k).."new:"..mobcount
  431. end
  432. end
  433. logappend("AAI_MOBCOUNT","Mobcount on well-behaved skill "..FormatSkill(skill,level).." range "..range.." logstring: "..logstring.." result: "..mobcount)
  434. end
  435. return mobcount
  436. end
  437.  
  438. function GetBestAoETarget(myid,skill,level)
  439. local mcount=0
  440. local result=-1
  441. for k,v in pairs(Targets) do
  442. if mcount < GetMobCount(skill,level,k,1) then
  443. result=k
  444. mcount=GetMobCount(skill,level,k,1)
  445. end
  446. end
  447. return result
  448. end
  449.  
  450. function GetBestAoECoord(myid,skill,level)
  451. local mcount =0
  452. local resultx = -1
  453. local resulty = -1
  454. local range=GetSkillInfo(skill,2,level)
  455. local aoesize=(SkillAOEInfo[skill][1][level]-1)/2
  456. local myx
  457. local myy
  458. myx,myy=GetV(V_POSITION,myid)
  459. local ox,oy=GetV(V_POSITION,GetV(V_OWNER,MyID))
  460. grid={}
  461. for xx=ox-20,ox+20 do
  462. grid[xx]={}
  463. --for xx=oy-20,oy+20 do
  464. -- grid[xx][yy]=0
  465. --end
  466. end
  467. for k,v in pairs(Targets) do
  468. local tbas = GetTact(TACT_BASIC,k)
  469. x,y=GetV(V_POSITION,k)
  470. if x < ox+20 and x > ox-20 and y < oy+20 and y > oy-20 and tbas~=0 then
  471. if grid[x][y]==nil then
  472. grid[x][y]=GetTact(TACT_WEIGHT,k)
  473. else
  474. grid[x][y]=grid[x][y]+GetTact(TACT_WEIGHT,k)
  475. end
  476. end
  477. end
  478. for xx=myx-range,myx+range do
  479. for yy=myy-range,myy+range do
  480. local thiscount=0
  481. for xxx=xx-aoesize,xx+aoesize do
  482. if grid[xxx]~=nil then
  483. for yyy=yy-aoesize,yy+aoesize do
  484. if grid[xxx][yyy] ~=nil then
  485. thiscount=thiscount+grid[xxx][yyy]
  486. end
  487. end
  488. end
  489. end
  490. if thiscount>mcount then
  491. mcount=thiscount
  492. resultx,resulty=xx,yy
  493. end
  494. end
  495. end
  496. return resultx,resulty
  497. end
  498.  
  499. function GetBestBrandishTarget(myid)
  500. local mobs =0
  501. local maxmobs = 0
  502. local besttarget= -1
  503. for k,v in pairs(Targets) do
  504. if (GetDistanceA(myid,k) <=1) then --Is a target in range to brandish
  505. mobs = 0
  506. for kk,vv in pairs (Targets) do
  507. local tbas=GetTact(TACT_BASIC,kk)
  508. if tbas ~= 0 then
  509. if (GetDistanceA(myid,kk)<=1 and GetDistanceA(k,kk) <=1) then
  510. mobs=mobs+1
  511. elseif (GetDistanceA(myid,kk) ==2 and GetDistance3(myid,kk) < 2.5 and GetDistance3(k,kk) < 2.5)then -- sides, 2 cells to either side of target/merc
  512. mobs=mobs+1
  513. end
  514. end
  515. end
  516. if (mobs > maxmobs) then
  517. maxmobs = mobs
  518. besttarget = v
  519. end
  520. end
  521. end
  522. return besttarget
  523. end
  524.  
  525. function GetBestFASTarget(myid)
  526. local options = GetFASOptions(myid)
  527. local mincount=0
  528. local target=-1
  529. for x,v in pairs(options) do
  530. for y,v2 in pairs(v) do
  531. --TraceAI("GetBestFAST "..x.." "..y.." "..v2)
  532. if v2~=0 then
  533. count=GetFASTargetCount(myid,x,y)
  534. if count > mincount then
  535. mincount = count
  536. target = v2
  537. end
  538. end
  539. end
  540. end
  541. return target,mincount
  542. end
  543.  
  544. function GetFASDirection(myid,target)
  545. local x,y=GetV(V_POSITION,myid)
  546. if GetDistanceA(myid,target) < 15 then
  547. local mx,my=GetV(V_POSITION,target)
  548. local dx=math.abs(x-mx)
  549. local dy=math.abs(y-my)
  550. if ((dx==0) or (dx==1 and dy>1) or (dx==2 and dy>6) or (dx==3 and dy>9) or (dx==4 and dy>11)) then
  551. if my>=y then
  552. return 0,1 --n
  553. elseif my<y then
  554. return 0,-1 --s
  555. end
  556. elseif ((dy==0) or (dy==1 and dx>1) or (dy==2 and dx>6) or (dy==3 and dx>9) or (dy==4 and dx>11)) then
  557. if mx>x then
  558. return 1,0 --e
  559. elseif mx<x then
  560. return-1,0 --w
  561. end
  562. -- diagonals
  563. elseif mx>x then
  564. if my>=y then
  565. return 1,1 --ne
  566. else
  567. return 1,-1 --se
  568. end
  569. elseif my>=y then
  570. return -1,1 --nw
  571. else
  572. return -1,-1 --sw
  573. end
  574. end
  575. end
  576.  
  577. function GetFASOptions(myid)
  578. local x,y=GetV(V_POSITION,myid)
  579. noption=0
  580. eoption=0
  581. soption=0
  582. woption=0
  583. neoption=0
  584. nwoption=0
  585. seoption=0
  586. swoption=0
  587. for k,v in pairs(Monsters) do
  588. TraceAI("FAS loop id: "..k)
  589. if GetDistanceA(myid,k) < 15 then
  590. mx,my=GetV(V_POSITION,k)
  591. dx=math.abs(x-mx)
  592. dy=math.abs(y-my)
  593. if ((dx==0) or (dx==1 and dy>1) or (dx==2 and dy>6) or (dx==3 and dy>9) or (dx==4 and dy>11)) then
  594. if my>y then
  595. noption=k
  596. elseif my<y then
  597. soption=k
  598. end
  599. elseif ((dy==0) or (dy==1 and dx>1) or (dy==2 and dx>6) or (dy==3 and dx>9) or (dy==4 and dx>11)) then
  600. if mx>x then
  601. eoption=k
  602. elseif mx<x then
  603. woption=k
  604. end
  605. -- diagonals
  606. elseif mx>x then
  607. if my>=y then
  608. neoption=k
  609. else
  610. seoption=k
  611. end
  612. elseif my>=y then
  613. nwoption=k
  614. else
  615. swoption=k
  616. end
  617. end
  618. if (noption~=0 and soption~=0 and eoption~=0 and woption~=0 and neoption~=0 and seoption~=0 and swoption~=0 and nwoption~=0) then
  619. TraceAI("All Options Avail - break")
  620. break
  621. end
  622. end
  623. result={[-1]={[-1]=swoption,[0]=woption,[1]=nwoption},[0]={[-1]=soption,[0]=0,[1]=noption},[1]={[-1]=seoption,[0]=eoption,[1]=neoption}}
  624. TraceAI("Returning FAS Options: "..swoption.."-"..woption.."-"..nwoption.." "..soption.."--"..noption.." "..seoption.."-"..eoption.."-"..neoption)
  625. return result
  626. end
  627.  
  628. function GetFASTargetCount(myid,directionx,directiony,aggro)
  629. local x,y=GetV(V_POSITION,myid)
  630. local s=directionx+directiony
  631. TraceAI("GFASTC: "..s)
  632. count=0
  633. if s==1 or s==-1 then -- straight
  634. if directiony==0 then --Horizontal
  635. ymin=y-1
  636. ymax=y+1
  637. if directionx==1 then --East
  638. xmin=x
  639. xmax=x+14
  640. else
  641. xmin=x-14
  642. xmax=x
  643. end
  644. else --Vertical
  645. xmin=x-1
  646. xmax=x+1
  647. if directiony==1 then -- north
  648. ymin=y
  649. ymax=y+14
  650. else
  651. ymin=y-14
  652. ymax=y
  653. end
  654. end
  655. for k,v in pairs(Targets) do
  656. mx,my=GetV(V_POSITION,k)
  657. --logappend("AAI_mobcount","straight monster:"..xmin.."-"..xmax..","..ymin.."-"..ymax.." "..mx..","..my)
  658. if GetTact(TACT_BASIC,k)~=0 and mx>=xmin and xmax>=mx and my>=ymin and ymax>=my then
  659. count=count+1
  660. end
  661. end
  662. --logappend("AAI_mobcount","straight:"..xmin.."-"..xmax..","..ymin.."-"..ymax.." count"..count)
  663. return count
  664. else --Diagonal
  665. count = 0
  666. for k,v in pairs(Targets) do
  667. if GetTact(TACT_BASIC,k)~=0 and IsNotKS(MyID,k)==1 then
  668. mx,my=GetV(V_POSITION,k)
  669. if directionx==1 then --east
  670. if (mx+1>=x and x+14>=mx) then -- has prayer of hitting
  671. if mx==x-1 then
  672. if my==y+directiony then
  673. count=count+1
  674. end
  675. elseif mx==x then
  676. if (my==y or my==y+directiony or my==y+2*directiony) then
  677. count=count+1
  678. end
  679. elseif mx==x+14 then
  680. if my==y+12*directiony then
  681. count=count+1
  682. end
  683. elseif mx==x+13 then
  684. if (my==y+11*directiony or my==y+10*directiony or my==y+12*directiony) then
  685. count=count+1
  686. end
  687. else --not a special case
  688. if directiony==1 then
  689. miny=y-2+(mx-x)
  690. maxy=miny+5
  691. else
  692. maxy=y+2-(mx-x)
  693. miny=maxy-5
  694. end
  695. if my>=miny and maxy>=my then
  696. count=count+1
  697. end
  698. end
  699. end
  700. else --west
  701. if mx-1<=x and x-14<=mx then -- has prayer of hitting
  702. if mx==x+1 then
  703. if my==y+directiony then
  704. count=count+1
  705. end
  706. elseif mx==x then
  707. if (my==y or my==y+directiony or my==y+2*directiony) then
  708. count=count+1
  709. end
  710. elseif mx==x-14 then
  711. if my==y+12*directiony then
  712. count=count+1
  713. end
  714. elseif mx==x-13 then
  715. if (my==y+11*directiony or my==y+10*directiony or my==y+12*directiony) then
  716. count=count+1
  717. end
  718. else --not a special case
  719. if directiony==1 then
  720. miny=y-2+(x-mx)
  721. maxy=miny+5
  722. else
  723. maxy=y+2-(x-mx)
  724. miny=maxy-5
  725. end
  726. if my>=miny and maxy>=my then
  727. count=count+1
  728. end
  729. end
  730. end
  731. end
  732. end
  733. end
  734. --logappend("AAI_mobcount","diagonal:"..count)
  735. end
  736. return count
  737. end
  738.  
  739. function IsHiddenOnScreen(myid) --Currently disabled - assume there is never hidden on screen.
  740. return 1
  741. end
  742.  
  743. function IsHomun(myid)
  744. if (GetV(V_HOMUNTYPE,myid)~=nil) then
  745. return 1
  746. end
  747. return 0
  748.  
  749. end
  750.  
  751. function GetMerType(myid)
  752. local merctype=GetV(V_MERTYPE,myid)
  753. TraceAI("Merc is homun?"..IsHomun(myid))
  754. if (merctype~=1) then
  755. return merctype
  756. elseif merctype > 30 then
  757. logappend("AAI_ERROR","Invalid merctype reported"..merctype)
  758. return merctype
  759. else
  760. mhp=GetV(V_MAXHP,myid)
  761. msp=GetV(V_MAXSP,myid)
  762. if (mhp > 250 and mhp < 333 and msp >= 200 and 250 >= msp ) then -- it's an archer 1
  763. return ARCHER01
  764. elseif (mhp == 7513 and msp == 201) then
  765. TraceAI("Newly summoned Pengineer")
  766. return PENGINEER
  767. elseif (mhp >= 4000 and 5000 >= mhp and msp >= 50 and msp < 65 ) then -- looks like a kitty!
  768. TraceAI("Wild Rose")
  769. return WILDROSE
  770. elseif (mhp >= 7513 and 8500 >= mhp and msp >= 201 and msp < 250 ) then
  771. TraceAI("Pengineer")
  772. return PENGINEER
  773. elseif (mhp >= 7200 and 7512 >= mhp and msp >= 200 and msp < 250 ) then -- looks like a dopple!
  774. TraceAI("Dopple Merc")
  775. return DOPPLEMERC
  776. elseif (mhp >= 10000 and 13000 >= mhp and msp >= 220 and msp < 300 ) then -- looks like alice!
  777. TraceAI("Alice")
  778. return ALICE
  779. elseif (mhp >= 6100 and 7200 >= mhp and msp >= 180 and msp < 250 ) then -- looks like a mimic!
  780. TraceAI("Mimic")
  781. return MIMIC
  782. elseif (mhp >= 7500 and 9500 >= mhp and msp >= 180 and msp < 220 ) then -- looks like a disguise!
  783. TraceAI("Disguise")
  784. return DISGUISE
  785. elseif (mhp >= 7000 and 8500 >= mhp and msp >= 250 and msp < 320 ) then -- looks like a male GM mercenary!
  786. TraceAI("GM Mercenary")
  787. return GMMALE
  788. elseif (mhp > 12300 and 14500 >= mhp and msp >= 450 and msp < 600 ) then -- Nice stats, must be one of them overpowerd isis mercs
  789. TraceAI("ISIS Mercenary")
  790. return ISIS
  791. else
  792. TraceAI("Unknown merc type. Contact the developer ASAP.")
  793. return UNKNOWNMER
  794. end
  795. end
  796. end
  797.  
  798. function IsNotKS(myid,target)
  799. --TraceAI("Checking for KS:"..target)
  800. local targettarget=GetV(V_TARGET,target)
  801. local motion=GetV(V_MOTION,target)
  802. local tactks=GetTact(TACT_KS,target)
  803. if (target==MyEnemy and BypassKSProtect==1) then --If owner has told homun to attack explicity, let it.
  804. return 1
  805. end
  806. if target==nil then
  807. TraceAI("IsNotKS")
  808. end
  809. if (IsPlayer(target)==1) then
  810. --TraceAI("PVP - not KS")
  811. return 1
  812. elseif (IsFriend(targettarget)==1 or targettarget==myid) then
  813. --TraceAI("Not KS - "..target.." fighting friend: "..targettarget)
  814. return 1
  815. elseif ((tactks==KS_POLITE or DoNotAttackMoving ==1) and motion==MOTION_MOVE) then
  816. return 0
  817. elseif (tactks==KS_ALWAYS) then
  818. --TraceAI("It's an FFA monster, not a KS")
  819. return 1
  820. elseif targettarget > 0 and IsMonster(targettarget)~=1 and Actors[targettarget]==1 then
  821. --TraceAI("Is KS - "..target.." attacking player "..targettarget.." motion "..motion)
  822. return 0
  823. else
  824. --TraceAI("Not Targeted - seeing if anyone is targeting it")
  825. local actors = GetActors()
  826. for i,v in ipairs(actors) do
  827. if (IsMonster(v)~=1 and IsFriendOrSelf(v)==0) then
  828. if (GetV(V_TARGET,v) == target and (v > 100000 or KSMercHomun ~=1)) then
  829. --TraceAI("Is KS - "..target.." is targeted by "..v)
  830. return 0
  831. end
  832. end
  833. end
  834. --TraceAI("Not KS - "..target.." is not targeted by any other player.")
  835. return 1
  836. end
  837. end
  838. function GetKSReason(myid,target)
  839. --TraceAI("Checking for KS:"..target)
  840. local targettarget=GetV(V_TARGET,target)
  841. local motion=GetV(V_MOTION,target)
  842. local tactks=GetTact(TACT_KS,target)
  843. if (target==MyEnemy and BypassKSProtect==1) then --If owner has told homun to attack explicity, let it.
  844. return "KS Protect bypassed"
  845. end
  846. if target==nil then
  847. TraceAI("IsNotKS")
  848. end
  849. if (IsPlayer(target)==1) then
  850. --TraceAI("PVP - not KS")
  851. return "PVP, not KS"
  852. elseif ((tactks==KS_POLITE or DoNotAttackMoving ==1) and motion==MOTION_MOVE) then
  853. return "KS polite aka DoNotAttackMoving"
  854. elseif (IsFriend(targettarget)==1 or targettarget==myid) then
  855. --TraceAI("Not KS - "..target.." fighting friend: "..targettarget)
  856. return "Not KS - enemy attacking "..targettarget
  857. elseif (tactks==KS_ALWAYS) then
  858. --TraceAI("It's an FFA monster, not a KS")
  859. return "FFA monster"
  860. elseif targettarget > 0 and IsMonster(targettarget)~=1 and Actors[targettarget]==1 then
  861. --TraceAI("Is KS - "..target.." attacking player "..targettarget.." motion "..motion)
  862. if MyFriends[targettarget]~=nil then
  863. return "KS - enemy is attacking "..targettarget.." MyFriends: "..MyFriends[targettarget]
  864. else
  865. return "KS - enemy is attacking "..targettarget
  866. end
  867. else
  868. --TraceAI("Not Targeted - seeing if anyone is targeting it")
  869. local actors = GetActors()
  870. for i,v in ipairs(actors) do
  871. if (IsMonster(v)~=1 and IsFriendOrSelf(v)==0) then
  872. if (GetV(V_TARGET,v) == target and (v > 100000 or KSMercHomun ~=1)) then
  873. --TraceAI("Is KS - "..target.." is targeted by "..v)
  874. if MyFriends[v]~=nil then
  875. return "KS - enemy attacked by "..v.." MyFriends: "..MyFriends[v]
  876. else
  877. return "KS - enemy attacked by "..v
  878. end
  879. end
  880. end
  881. end
  882. --TraceAI("Not KS - "..target.." is not targeted by any other player.")
  883. return "not KS, not targeted by anything"
  884. end
  885. end
  886. --########################
  887. --### HP/SP % functions###
  888. --########################
  889.  
  890. function HPPercent(id)
  891. local maxHP=GetV(V_MAXHP,id)
  892. local curHP=GetV(V_HP,id)
  893. percHP=100*curHP/maxHP
  894. return percHP
  895. end
  896.  
  897. function SPPercent(id)
  898. local maxSP=GetV(V_MAXSP,id)
  899. local curSP=GetV(V_SP,id)
  900. percSP=100*curSP/maxSP
  901. return percSP
  902. end
  903.  
  904. --########################
  905. --### Spacial functions###
  906. --########################
  907. OldMove=Move
  908.  
  909. function Move(myid,x,y)
  910. local ox,oy = GetV(V_POSITION,myid)
  911. local dis = GetDistance(ox,oy,x,y)
  912. local dis2owner=GetDistanceAPR(GetV(V_OWNER,myid),x,y)
  913. local newx,newy=x,y
  914. if dis2owner > 14 then
  915. logappend("AAI_ERROR","Attempt to move to location "..x..","..y.." which is "..dis2owner.." cells from owner, call disregarded")
  916. return
  917. elseif dis > 15 then
  918. factor = 15/dis
  919. local dx,dy = x-ox,y-oy
  920. if math.random(2)==1 then
  921. dx=math.ceil(factor*dx)
  922. else
  923. dx=math.floor(factor*dx)
  924. end
  925. if math.random(2)==1 then
  926. dy=math.ceil(factor*dy)
  927. else
  928. dy=math.floor(factor*dy)
  929. end
  930. if _VERSION=="Lua 5.1" then
  931. while TakenCells[(x+dx).."_"..(y+dy)] do
  932. factor=factor-0.08
  933. if math.random(2)==1 then
  934. dx=math.ceil(factor*(x-ox))
  935. else
  936. dx=math.floor(factor*(x-ox))
  937. end
  938. if math.random(2)==1 then
  939. dy=math.ceil(factor*(y-oy))
  940. else
  941. dy=math.floor(factor*(y-oy))
  942. end
  943. end
  944. end
  945. if x==MyDestX and y==MyDestY then
  946. newx=ox+dx
  947. newy=oy+dy
  948. MyDestX,MyDestY=newx,newy
  949. TraceAI("MOVE: Attempt to move more than 15 cells, destination + MyDest adjusted: "..x..","..y.." "..dis.." "..factor.."new: "..newx..","..newy)
  950. else
  951. newx=ox+dx
  952. newy=oy+dy
  953. TraceAI("MOVE: Attempt to move more than 15 cells, destination adjusted: "..x..","..y.." "..dis.." "..factor.."new: "..newx..","..newy)
  954. end
  955. end
  956. if (LagReduction) then
  957. modtwROMoveX,modtwROMoveY=x,y
  958. return
  959. else
  960. return OldMove(myid,newx,newy)
  961. end
  962. end
  963.  
  964.  
  965. OldSkillObject=SkillObject
  966. function SkillObject(myid,lvl,skill,target)
  967. if skill==8041 or skill==8043 or skill==8020 or skill==8025 then
  968. logappend("AAI_ERROR","Attempted to use skill "..SkillInfo[skill][1].." improperly. Check for corrupt H_SkillInfo or badly behaved addon")
  969. else
  970. if (LagReduction) then
  971. modtwROSkillObjectID=skill
  972. modtwROSkillObjectLV=lvl
  973. modtwROSkillObjectTarg=target
  974. else
  975. return OldSkillObject(myid,lvl,skill,target)
  976. end
  977. end
  978. end
  979.  
  980. OldAttack=Attack
  981. function Attack(myid,target)
  982. if SuperPassive==1 then
  983. TraceAI("Notice: Attack() called while in SuperPassive. MyEnemy "..MyEnemy.." MyState "..MyState)
  984. end
  985. if (LagReduction) then
  986. modtwROAttackTarget=target
  987. else
  988. return OldAttack(myid,target)
  989. end
  990. end
  991.  
  992. OldSkillGround=SkillGround
  993. function SkillGround(myid,lvl,skill,x,y)
  994. if (LagReduction) then
  995. modtwROSkillGroundX=x
  996. modtwROSkillGroundY=y
  997. modtwROSkillGroundID=skill
  998. modtwROSkillGroundLV=lvl
  999. else
  1000. return OldSkillGround(myid,lvl,skill,x,y)
  1001. end
  1002. end
  1003.  
  1004. function GetDistance (x1,y1,x2,y2)
  1005. return math.floor(math.sqrt((x1-x2)^2+(y1-y2)^2))
  1006. end
  1007.  
  1008. function GetDistance2 (id1, id2)
  1009. local x1, y1 = GetV (V_POSITION,id1)
  1010. local x2, y2 = GetV (V_POSITION,id2)
  1011. if (x1 == -1 or x2 == -1) then
  1012. return -1
  1013. end
  1014. return GetDistance (x1,y1,x2,y2)
  1015. end
  1016.  
  1017.  
  1018. function GetDistanceA (id1, id2)
  1019. local x1, y1 = GetV (V_POSITION,id1)
  1020. local x2, y2 = GetV (V_POSITION,id2)
  1021. if (x1 == -1 or x2 == -1) then
  1022. return 999
  1023. end
  1024. return GetDistance (x1,y1,x2,y2)
  1025. end
  1026.  
  1027. function GetDistanceAP (id1, x2,y2)
  1028. local x1, y1 = GetV (V_POSITION,id1)
  1029. if (x1 == -1 or x2 == -1) then
  1030. return 999
  1031. end
  1032. return GetDistance (x1,y1,x2,y2)
  1033. end
  1034.  
  1035. function GetDistanceAPR (id1, x2,y2)
  1036. local x1, y1 = GetV (V_POSITION,id1)
  1037. if (x1 == -1 or x2 == -1) then
  1038. return 999
  1039. end
  1040. local x=x1-x2
  1041. local y=y1-y2
  1042. return math.max(math.abs(x),math.abs(y))
  1043. end
  1044.  
  1045. function GetDistanceRect(id1,id2)
  1046. local x1, y1 = GetV (V_POSITION,id1)
  1047. local x2, y2 = GetV (V_POSITION,id2)
  1048. if (x1 == -1 or x2 == -1) then
  1049. return 999
  1050. end
  1051. local x=x1-x2
  1052. local y=y1-y2
  1053. return math.max(math.abs(x),math.abs(y))
  1054. end
  1055.  
  1056. function GetDistance3(id1,id2)
  1057. local x1, y1 = GetV (V_POSITION,id1)
  1058. local x2, y2 = GetV (V_POSITION,id2)
  1059. if (x1 == -1 or x2 == -1) then
  1060. return -1
  1061. end
  1062. return math.sqrt((x1-x2)^2+(y1-y2)^2)
  1063. end
  1064.  
  1065. function GetAggroDist()
  1066. if OwnerPosX[10]==OwnerPosX[1] and OwnerPosY[10]==OwnerPosY[1] then
  1067. return StationaryAggroDist
  1068. else
  1069. return MobileAggroDist
  1070. end
  1071. end
  1072.  
  1073. function GetMoveBounds()
  1074. if OwnerPosX[10]==OwnerPosX[1] and OwnerPosY[10]==OwnerPosY[1] then
  1075. return StationaryMoveBounds
  1076. else
  1077. return MobileMoveBounds
  1078. end
  1079. end
  1080. function IsToRight(id1,id2)
  1081. local x1,y1=GetV(V_POSITION,id1)
  1082. local x2,y2=GetV(V_POSITION,id2)
  1083. if (x1+1==x2 and y1==y2) then
  1084. return 1
  1085. else
  1086. return 0
  1087. end
  1088. end
  1089.  
  1090. function GetDistanceP (x1,y1,x2,y2)
  1091. if (x1 == -1 or x2 == -1) then
  1092. return 999
  1093. end
  1094. return math.floor(math.sqrt((x1-x2)^2+(y1-y2)^2))
  1095. end
  1096.  
  1097. function GetDistanceA (id1, id2)
  1098. local x1, y1 = GetV (V_POSITION,id1)
  1099. local x2, y2 = GetV (V_POSITION,id2)
  1100. if (x1 == -1 or x2 == -1) then
  1101. return 999
  1102. end
  1103. return GetDistance (x1,y1,x2,y2)
  1104. end
  1105.  
  1106. function GetDistanceAP (id1, x2,y2)
  1107. local x1, y1 = GetV (V_POSITION,id1)
  1108. if (x1 == -1 or x2 == -1) then
  1109. return 999
  1110. end
  1111. return GetDistance (x1,y1,x2,y2)
  1112. end
  1113.  
  1114. function GetDistancePR (x1,y1,x2,y2)
  1115. if (x1 == -1 or x2 == -1) then
  1116. return 999
  1117. end
  1118. return math.max(math.abs(x1-x2),math.abs(y1-y2))
  1119. end
  1120.  
  1121. function GetDistanceAR(id1,id2)
  1122. local x1, y1 = GetV (V_POSITION,id1)
  1123. local x2, y2 = GetV (V_POSITION,id2)
  1124. if (x1 == -1 or x2 == -1) then
  1125. return 999
  1126. end
  1127. return math.max(math.abs(x1-x2),math.abs(y1-y2))
  1128. end
  1129.  
  1130. function GetDistanceAPR (id1, x2,y2)
  1131. local x1, y1 = GetV (V_POSITION,id1)
  1132. if (x1 == -1 or x2 == -1) then
  1133. return 999
  1134. end
  1135. return math.max(math.abs(x1-x2),math.abs(y1-y2))
  1136. end
  1137.  
  1138.  
  1139.  
  1140.  
  1141.  
  1142.  
  1143. function BetterMoveToOwner(myid,range)
  1144. if (range==nil) then
  1145. range=1
  1146. end
  1147. local x,y = GetV(V_POSITION,myid)
  1148. local ox,oy = GetV(V_POSITION,GetV(V_OWNER,myid))
  1149. local destx,desty=0,0
  1150. if (x > ox+range) then
  1151. destx=ox+range
  1152. elseif (x < ox - range) then
  1153. destx=ox-range
  1154. else
  1155. destx=x
  1156. end
  1157. if (y > oy+range) then
  1158. desty=oy+range
  1159. elseif (y < oy - range) then
  1160. desty=oy-range
  1161. else
  1162. desty=y
  1163. end
  1164. MyDestX,MyDestY=destx,desty
  1165. Move(myid,MyDestX,MyDestY)
  1166. return
  1167. end
  1168. function BetterMoveToOwnerXY(myid,range)
  1169. if (range==nil) then
  1170. range=1
  1171. end
  1172. local x,y = GetV(V_POSITION,myid)
  1173. local ox,oy = GetV(V_POSITION,GetV(V_OWNER,myid))
  1174. local destx,desty=0,0
  1175. if (x > ox+range) then
  1176. destx=ox+range
  1177. elseif (x < ox - range) then
  1178. destx=ox-range
  1179. else
  1180. destx=x
  1181. end
  1182. if (y > oy+range) then
  1183. desty=oy+range
  1184. elseif (y < oy - range) then
  1185. desty=oy-range
  1186. else
  1187. desty=y
  1188. end
  1189. return destx,desty
  1190. end
  1191. function BetterMoveToLoc(myid,range,ox,oy)
  1192. if (range==nil) then
  1193. range=1
  1194. end
  1195. local x,y = GetV(V_POSITION,myid)
  1196. --local ox,oy = GetV(V_POSITION,GetV(V_OWNER,myid))
  1197. local destx,desty=0,0
  1198. if (x > ox+range) then
  1199. destx=ox+range
  1200. elseif (x < ox - range) then
  1201. destx=ox-range
  1202. else
  1203. destx=x
  1204. end
  1205. if (y > oy+range) then
  1206. desty=oy+range
  1207. elseif (y < oy - range) then
  1208. desty=oy-range
  1209. else
  1210. desty=y
  1211. end
  1212. MyDestX,MyDestY=destx,desty
  1213. Move(myid,MyDestX,MyDestY)
  1214. return
  1215. end
  1216. function BetterMoveToLocXY(myid,range,ox,oy)
  1217. if (range==nil) then
  1218. range=1
  1219. end
  1220. local x,y = GetV(V_POSITION,myid)
  1221. --local ox,oy = GetV(V_POSITION,GetV(V_OWNER,myid))
  1222. local destx,desty=0,0
  1223. if (x > ox+range) then
  1224. destx=ox+range
  1225. elseif (x < ox - range) then
  1226. destx=ox-range
  1227. else
  1228. destx=x
  1229. end
  1230. if (y > oy+range) then
  1231. desty=oy+range
  1232. elseif (y < oy - range) then
  1233. desty=oy-range
  1234. else
  1235. desty=y
  1236. end
  1237.  
  1238. return destx,desty
  1239. end
  1240.  
  1241. function GetOwnerPosition (id)
  1242. return GetV (V_POSITION,GetV(V_OWNER,id))
  1243. end
  1244.  
  1245. function GetDistanceFromOwner (id)
  1246. local x1, y1 = GetOwnerPosition (id)
  1247. local x2, y2 = GetV (V_POSITION,id)
  1248. if (x1 == -1 or x2 == -1) then
  1249. return -1
  1250. end
  1251. return GetDistance (x1,y1,x2,y2)
  1252. end
  1253.  
  1254. function IsOutOfSight (id1,id2)
  1255. local x1,y1 = GetV (V_POSITION,id1)
  1256. local x2,y2 = GetV (V_POSITION,id2)
  1257. if (x1 == -1 or x2 == -1 or id1==-1 or id2==-1) then
  1258. return true
  1259. end
  1260. local d = GetDistancePR(x1,y1,x2,y2)
  1261. if d > 20 then
  1262. return true
  1263. else
  1264. return false
  1265. end
  1266. end
  1267.  
  1268.  
  1269. function IsInAttackSight (myid,target,skill,level)
  1270. if (skill==nil) then
  1271. skill=MySkill
  1272. level=MySkillLevel
  1273. elseif (level==nil) then
  1274. logappend("AAI_ERROR","IsInAttackSight called with nil level but skill is not nil. State:"..MyState.." skill "..skill)
  1275. end
  1276. local x1,y1 = GetV (V_POSITION,myid)
  1277. local x2,y2 = GetV (V_POSITION,target)
  1278. if (x1 == -1 or x2 == -1) then
  1279. return false
  1280. end
  1281. local d = GetDistance (x1,y1,x2,y2)
  1282. local a = AttackRange(myid,skill,level)
  1283. if a >= d then
  1284. return true;
  1285. else
  1286. return false;
  1287. end
  1288. end
  1289.  
  1290.  
  1291.  
  1292. function AttackRange(myid,skill,level)
  1293. if (skill==nil or level== nil) then
  1294. if skill==nil or level==nil then
  1295. logappend("AAI_ERROR","AttackRange called with invalid arguments State:"..MyState.." MySkill "..MySkill.." MySkillLevel"..MySkillLevel.." skill: "..formatval(skill).." level: "..formatval(level))
  1296. end
  1297. skill=MySkill
  1298. level=MySkillLevel
  1299. end
  1300. local a = 0
  1301. if (skill == 0) then
  1302. mertype=GetMerType(myid)
  1303. if (mertype==nil) then
  1304. mertype=-1
  1305. end
  1306. if (mertype == -1) then
  1307. a = 1
  1308. elseif (mertype > 10 and mertype < 21) then
  1309. a = 2 --spear mercenary
  1310. else
  1311. a = GetV(V_ATTACKRANGE,myid)
  1312. end
  1313. --elseif (skill==MS_BOWLINGBASH) then
  1314. -- a = 1
  1315. else
  1316. a = GetSkillInfo(skill,2,level)
  1317. if a==nil then
  1318. TraceAI("AttackRange() cannot get range for skill "..formatval(skill).." level "..formatval(level))
  1319. end
  1320. end
  1321. if level == nil then
  1322. logappend("AAI_ERROR","AttackRange called with nil level, skill = "..skill.." "..MyState)
  1323. end
  1324. TraceAI("Attack Sight - skill:"..skill.."level: "..level.." Range:"..a)
  1325. return a
  1326. end
  1327.  
  1328. function Closer(id,ox,oy)
  1329. local x,y=GetV(V_POSITION,id)
  1330. local newx,newy=0,0
  1331. if (ox==x) then
  1332. newx=x
  1333. elseif (ox > x) then
  1334. newx=ox-1
  1335. else
  1336. newx=ox+1
  1337. end
  1338. if (oy==y) then
  1339. newy=y
  1340. elseif (oy > y) then
  1341. newy=oy-1
  1342. else
  1343. newy=oy+1
  1344. end
  1345. return newx,newy
  1346. end
  1347.  
  1348.  
  1349.  
  1350.  
  1351. function GetStandPoint(myid,target,skill,level,alt)
  1352. local r=AttackRange(myid,skill,level)
  1353. if GetDistanceA(myid,target) <= r then
  1354. logappend("AAI_ERROR","GetStandPoint called while within range")
  1355. return GetV(V_POSITION,MyID)
  1356. end
  1357. local tx,ty=GetV(V_POSITION,target)
  1358. local x,y=-1,-1
  1359. if _VERSION=="Lua 5.1" and myid==MyID and (alt==nil or alt==0) then
  1360. x,y=GetV(V_POSITION_APPLY_SKILLATTACKRANGE,target,skill,level)
  1361. end
  1362. if skill==0 or skill==nil or (tx==x and ty==y) or (tx < 1 or ty < 1) or math.floor(GetDistanceAP(target,x,y)) > r then -- Use normal closest call, since V_POSITION_APPLY_SKILLATTACKRANGE doesn't work for non-skills, or has given us clearly bogus standpoint for skill.
  1363. x,y=Closest(myid,tx,ty,r,alt)
  1364. end
  1365. return AdjustStandPoint(x,y,tx,ty,r,alt)
  1366. end
  1367.  
  1368. function AdjustStandPoint (x,y,tx,ty,r,alt)
  1369. if _VERSION=="Lua 5.1" then
  1370. -- Now we need to make sure x and y are not on occupied cells, because of the changes to the client
  1371. local i=0
  1372. local bounds=GetMoveBounds()
  1373. while (TakenCells[x.."_"..y] or GetDistanceAP(MyID,x,y) > bounds) do
  1374. i=i+1
  1375. if r==1 then
  1376. if alt==nil or alt==0 then
  1377. x,y=AdjustCW(x,y,tx,ty)
  1378. elseif alt==1 then
  1379. x,y=AdjustCCW(x,y,tx,ty)
  1380. else --alt=2
  1381. x,y=AdjustOpp(x,y,tx,ty)
  1382. alt=0
  1383. end
  1384. if i > 7 then
  1385. return -1,-1
  1386. end
  1387. else
  1388. if alt==nil or alt==0 then
  1389. x,y=AdjustCWr(x,y,tx,ty,r)
  1390. elseif alt==1 then
  1391. x,y=AdjustCCWr(x,y,tx,ty,r)
  1392. else --alt=2
  1393. x,y=x*-1,y*-1
  1394. alt=0
  1395. end
  1396. if i > 7 then
  1397. return -1,-1
  1398. end
  1399. end
  1400. end
  1401. end
  1402. return x,y
  1403. end
  1404.  
  1405. function Closest(myid,ox,oy,range,alt)
  1406. local x,y=GetV(V_POSITION,myid)
  1407. local dx,dy=ox-x,oy-y
  1408. local newx,newy=0,0
  1409. local logstring="x,y"..x..","..y.." ox,oy"..ox..","..oy
  1410. if range > 1 then
  1411. logstring=logstring.."range > 1 "
  1412. dist=math.sqrt(dx^2+dy^2)
  1413. if (dist < range) then
  1414. newx,newy=x,y
  1415. logstring=logstring.."dist < range new"..newx..","..newy.." "
  1416. else
  1417. factor=range/dist
  1418. xoff=(dx-absceil(dx*factor))
  1419. yoff=(dy-absceil(dy*factor))
  1420. newx,newy=x+xoff,y+yoff
  1421. logstring=logstring.."dist > range new" ..newx..","..newy.." factor:"..factor.." "
  1422. end
  1423. -- This routine tries to find an adjacent cell to the closest cell that will be close enough - to address unwalkable cells near where retainer wants to walk (think: pebbles in thors)
  1424.  
  1425. if (alt ~= nil) then
  1426. logstring=logstring.."alt not nil"..alt.." "
  1427. if (alt==1) then
  1428. if (x > ox) then
  1429. newx=newx-1
  1430. elseif (x < ox) then
  1431. newx=newx+1
  1432. else
  1433. alt=2
  1434. end
  1435. end
  1436. if (alt==2) then
  1437. if (y > oy) then
  1438. newy=newy-1
  1439. elseif (y < oy) then
  1440. newy=newy+1
  1441. else
  1442. alt=3
  1443. end
  1444. end
  1445.  
  1446. --if (alt==4) then -- This seems to cause more problems than it solves, set to 4 to prevent from running
  1447. -- if (x > ox) then
  1448. -- newx=newx-1
  1449. -- newy=newy+1
  1450. -- elseif (x < ox) then
  1451. -- newx=newx+1
  1452. -- newy=newy+1
  1453. -- elseif (y > oy) then
  1454. -- newy=newy-1
  1455. -- newx=newx+1
  1456. -- else
  1457. -- newy=newy+1
  1458. -- newx=newx+1
  1459. -- end
  1460. --end
  1461. logstring=logstring.."end of alt sequence new"..newx..","..newy.." alt "..alt.." "
  1462. end
  1463. --xxx,yyy=GetV(V_POSITION,target)
  1464. --TraceAI("alt is: "..GetDistance(xxx,yyy,newx,newy).." "..xxx..","..yyy.." "..newx..","..newy.."MyPos: "..x..","..y)
  1465. else -- simplified, better closest point for melee.
  1466. logstring=logstring.."range = 1 d"..dx..","..dy.." o"..ox..","..oy.." "
  1467. if dx > 0 then
  1468. newx=ox-1
  1469. elseif dx < 0 then
  1470. newx=ox+1
  1471. else -- dx = 0
  1472. newx=x
  1473. end
  1474. if dy > 0 then
  1475. newy=oy-1
  1476. elseif dy < 0 then
  1477. newy=oy+1
  1478. else -- dy = 0
  1479. newy=y
  1480. end
  1481. logstring=logstring.."new"..newx..","..newy.." "
  1482. if alt~=nil then
  1483. if alt==1 then
  1484. newx,newy=AdjustCW(newx,newy,ox,oy)
  1485. logstring=logstring.."adjust cw"..newx..","..newy.." "
  1486. else
  1487. newx,newy=AdjustCCW(newx,newy,ox,oy)
  1488. logstring=logstring.."adjust ccw"..newx..","..newy.." "
  1489. end
  1490. end
  1491. end
  1492. local logalt="nil"
  1493. if alt~=nil then
  1494. logalt=alt
  1495. end
  1496. if newx<=0 or newy<=0 then
  1497. logappend("AAI_ERROR","Closest() Failure!"..newx.." , "..newy.." alt ="..logalt.." logstring="..logstring)
  1498. end
  1499. logappend("AAI_CLOSEST","Closest() returned "..newx.." , "..newy.." alt ="..logalt.." logstring="..logstring)
  1500. return newx,newy
  1501. end
  1502.  
  1503. function AdjustCW(x,y,ox,oy)
  1504. local newx,newy,dy,dx
  1505. if x==ox then
  1506. if y==oy then --stacked!? Unstack!
  1507. newx,newy=ox+1,oy
  1508. else
  1509. dy=y-oy
  1510. newx=x+absunit(dy)
  1511. newy=y
  1512. end
  1513. elseif y==oy then
  1514. dx=x-ox
  1515. newy=y-absunit(dx)
  1516. newx=x
  1517. elseif y>oy then
  1518. if x>ox then
  1519. newy=y-1
  1520. newx=x
  1521. else
  1522. newy=y
  1523. newx=x+1
  1524. end
  1525. else -- y<oy
  1526. if x>ox then
  1527. newx=x-1
  1528. newy=y
  1529. else
  1530. newx=x
  1531. newy=y+1
  1532. end
  1533. end
  1534. return newx,newy
  1535. end
  1536. function AdjustCCW(x,y,ox,oy)
  1537. local newx,newy,dx,dy
  1538. if x==ox then
  1539. if y==oy then --stacked!? Unstack!
  1540. newx,newy=ox-1,oy
  1541. else
  1542. dy=y-oy
  1543. newx=x-absunit(dy)
  1544. newy=y
  1545. end
  1546. elseif y==oy then
  1547. dx=x-ox
  1548. newy=y+absunit(dx)
  1549. newx=x
  1550. elseif y>oy then
  1551. if x>ox then
  1552. newy=y
  1553. newx=x-1
  1554. else
  1555. newy=y-1
  1556. newx=x
  1557. end
  1558. else -- y<oy
  1559. if x>ox then
  1560. newx=x
  1561. newy=y+1
  1562. else
  1563. newx=x+1
  1564. newy=y
  1565. end
  1566. end
  1567. return newx,newy
  1568. end
  1569.  
  1570. function AdjustCWr(x,y,ox,oy,r)
  1571. if r==1 then
  1572. return AdjustCW(x,y,ox,oy)
  1573. end
  1574. local newx,newy,dy,dx
  1575. dx,dy=x-ox,y-oy
  1576. if math.abs(dx) == math.abs(dy) then --we're on a diagonal, this could be a problem, so let's get off it!
  1577. if dx < 0 then
  1578. if dy < 0 then
  1579. newx=x+1
  1580. newy=y
  1581. else
  1582. newx=x
  1583. newy=y-1
  1584. end
  1585. elseif dx > 0 then
  1586. if dy < 0 then
  1587. newy=y+1
  1588. newx=x
  1589. else
  1590. newx=x-1
  1591. newy=y
  1592. end
  1593. else --stacked, which should NEVER HAPPEN but has somehow happened anyway
  1594. newx=x+1
  1595. newy=y+1
  1596. logappend("AAI_ERROR","AdjustCWr called with x,y=ox,oy - this can't happen!")
  1597. end
  1598. else
  1599. if math.abs(dx) < math.abs(dy) then --north or south quadrant
  1600. if dy < 0 then -- south quadrant
  1601. newx=x+1
  1602. newy=y+1
  1603. else --north
  1604. newx=x-1
  1605. newy=y-1
  1606. end
  1607. else --east or west quadrant
  1608. if dx < 0 then --west
  1609. newy=y-1
  1610. newx=x+1
  1611. else
  1612. newx=x-1
  1613. newy=y+1
  1614. end
  1615. end
  1616. end
  1617.  
  1618. if (newx-ox==0 and math.abs(newy-oy)==1) or (newy-oy==0 and math.abs(newx-ox)==1) then
  1619. newx,newy=newx*2,newy*2
  1620. end
  1621. return newx,newy
  1622. end
  1623.  
  1624. function AdjustCCWr(x,y,ox,oy,r)
  1625. if r==1 then
  1626. return AdjustCCW(x,y,ox,oy)
  1627. end
  1628. local newx,newy,dy,dx
  1629. dx,dy=x-ox,y-oy
  1630. if math.abs(dx) == math.abs(dy) then --we're on a diagonal, this could be a problem, so let's get off it!
  1631. if dx < 0 then
  1632. if dy < 0 then
  1633. newx=x
  1634. newy=y+1
  1635. else
  1636. newx=x+1
  1637. newy=y
  1638. end
  1639. elseif dx > 0 then
  1640. if dy < 0 then
  1641. newy=y
  1642. newx=x-1
  1643. else
  1644. newx=x
  1645. newy=y-1
  1646. end
  1647. else --stacked, which should NEVER HAPPEN but has somehow happened anyway
  1648. newx=x-1
  1649. newy=y-1
  1650. logappend("AAI_ERROR","AdjustCWr called with x,y=ox,oy - this can't happen!")
  1651. end
  1652. else
  1653. if math.abs(dx) < math.abs(dy) then --north or south quadrant
  1654. if dy < 0 then -- south quadrant
  1655. newx=x-1
  1656. newy=y+1
  1657. else --north
  1658. newx=x+1
  1659. newy=y-1
  1660. end
  1661. else --east or west quadrant
  1662. if dx < 0 then --west
  1663. newy=y+1
  1664. newx=x+1
  1665. else
  1666. newx=x-1
  1667. newy=y-1
  1668. end
  1669. end
  1670. end
  1671. if (newx-ox==0 and math.abs(newy-oy)==1) or (newy-oy==0 and math.abs(newx-ox)==1) then
  1672. newx,newy=newx*2,newy*2
  1673. end
  1674. return newx,newy
  1675. end
  1676.  
  1677. function AdjustOpp(x,y,ox,oy)
  1678. dx=ox-x
  1679. dy=oy-y
  1680. return x+2*dx,y+2*dy
  1681. end
  1682. function ClosestR(myid,target,range,alt)
  1683. local ox,oy=GetV(V_POSITION,target)
  1684. return Closest(myid,ox,oy,range,alt)
  1685. end
  1686.  
  1687. --############################### ## ##
  1688. --### LUA 5.1 feature support ### ## ##
  1689. --############################### ## ##
  1690.  
  1691.  
  1692. function DiagonalDist(distance)
  1693. return math.floor(math.sqrt(distance*distance))
  1694. end
  1695.  
  1696. function GetDanceCell(x,y,enemy)
  1697. local enemyx,enemyy=GetV(V_POSITION,enemy)
  1698. if IsInAttackSight(MyID,enemy) == false then --Why is this being called?!
  1699. logappend("AAI_ERROR","GetDanceCell() called when enemy out of range!" )
  1700. x,y=Closest(MyID,enemyx,enemyy,1)
  1701. return x,y
  1702. end
  1703. t = math.random(2)
  1704. if t == 1 then
  1705. return AdjustCW(x,y,enemyx,enemyy)
  1706. elseif t == 2 then
  1707. return AdjustCCW(x,y,enemyx,enemyy)
  1708. else
  1709. return AdjustOpp(x,y,enemyx,enemyy)
  1710. end
  1711. end
  1712.  
  1713. --[[ --disabled for a simpler dance alog, because you can't dance any ranged attacks at the moment, so optimize for range=1
  1714.  
  1715. function GetDanceCell(x,y,enemy)
  1716. distance = GetDistance2(MyID,enemy)
  1717. ex,ey=GetV(V_POSITION,enemy)
  1718. s=(((math.random(2)-1)*2)-1)
  1719. t=(((math.random(2)-1)*2)-1)
  1720. if (GetDistance(x-s,y+t,ex,ey) == distance) then
  1721. return x-s,y+t
  1722. elseif (GetDistance(x,y+t,ex,ey) == distance) then
  1723. return x,y+t
  1724. elseif (GetDistance(x+s,y+t,ex,ey) == distance) then
  1725. return x+s,y+t
  1726. elseif (GetDistance(x-s,y,ex,ey) == distance) then
  1727. return x-s,y
  1728. elseif (GetDistance(x+s,y,ex,ey) == distance) then
  1729. return x+s,y
  1730. elseif (GetDistance(x-s,y-t,ex,ey) == distance) then
  1731. return x-s,y-t
  1732. elseif (GetDistance(x,y-t,ex,ey) == distance) then
  1733. return x,y-t
  1734. else
  1735. return x+s,y-t
  1736. end
  1737.  
  1738. end
  1739. ]]--]]
  1740. --#########################
  1741. --### GetSkill functions###
  1742. --#########################
  1743.  
  1744. function GetSAtkSkill(myid)
  1745. local skill = 0
  1746. local level = 0
  1747. if (IsHomun(myid)==1) then
  1748. htype=GetV(V_HOMUNTYPE,myid)
  1749. if htype > 47 then -- it's a Homun S
  1750. if htype==EIRA and UseEiraEraseCutter==1 then
  1751. skill=MH_ERASER_CUTTER
  1752. if EiraEraseCutterLevel==nil then
  1753. level=4
  1754. else
  1755. level=EiraEraseCutterLevel
  1756. end
  1757. elseif htype==BAYERI and UseBayeriStahlHorn==1 then
  1758. skill=MH_STAHL_HORN
  1759. if BayeriStahlHornLevel==nil then
  1760. level=5
  1761. else
  1762. level=BayeriStahlHornLevel
  1763. end
  1764. elseif htype==SERA and UseSeraParalyze==1 then
  1765. skill=MH_NEEDLE_OF_PARALYZE
  1766. if SeraParalyzeLevel==nil then
  1767. level=5
  1768. else
  1769. level=SeraParalyzeLevel
  1770. end
  1771. elseif htype==ELEANOR and UseEleanorSonicClaw==1 and ( EleanorMode==0 or EleanorDoNotSwitchMode==1 ) then
  1772. skill=MH_SONIC_CRAW
  1773. if EleanorSonicClawLevel==nil then
  1774. level=5
  1775. else
  1776. level=EleanorSonicClawLevel
  1777. end
  1778. elseif htype==ELEANOR and UseEleanorTinderBreaker==1 and EleanorMode==1 then
  1779. skill=MH_TINDER_BREAKER
  1780. if EleanorTinderBreakerLevel==nil then
  1781. level=5
  1782. else
  1783. level=EleanorTinderBreakerLevel
  1784. end
  1785. end
  1786. end
  1787. if level ~=0 then
  1788. return skill,level
  1789. end
  1790. end
  1791. return 0,0
  1792. end
  1793.  
  1794. function GetComboSkill(myid)
  1795. local skill = 0
  1796. local level = 0
  1797. if (IsHomun(myid)==1) then
  1798. htype=GetV(V_HOMUNTYPE,myid)
  1799. if htype==ELEANOR then
  1800. if EleanorMode==0 or EleanorDoNotSwitchMode==1 then
  1801. if ComboSCTimeout > GetTick() and MySpheres >= AutoComboSpheres then
  1802. skill=MH_SILVERVEIN_RUSH
  1803. if EleanorSilverveinLevel==nil then
  1804. level=5
  1805. else
  1806. level=EleanorSilverveinLevel
  1807. end
  1808. elseif ComboSVTimeout > GetTick() then
  1809. skill=MH_MIDNIGHT_FRENZY
  1810. if EleanorMidnightLevel==nil then
  1811. level=5
  1812. else
  1813. level=EleanorMidnightLevel
  1814. end
  1815. end
  1816. end
  1817. end
  1818. if level ~=0 then
  1819. return skill,level
  1820. end
  1821. end
  1822. return 0,0
  1823. end
  1824.  
  1825. function GetGrappleSkill(myid)
  1826. local skill = 0
  1827. local level = 0
  1828. if (IsHomun(myid)==1) then
  1829. htype=GetV(V_HOMUNTYPE,myid)
  1830. if htype==ELEANOR and MySpheres >= AutoComboSpheres then
  1831. if EleanorMode==1 or EleanorDoNotSwitchMode==1 then
  1832. if ComboSCTimeout > GetTick() then
  1833. if MySpheres >= AutoComboSpheres -1 then
  1834. skill=MH_CBC
  1835. if EleanorCBCLevel==nil then
  1836. level=5
  1837. else
  1838. level=EleanorCBCLevel
  1839. end
  1840. end
  1841. elseif ComboSVTimeout > GetTick() then
  1842. if MySpheres >= AutoComboSpheres -1 then
  1843. skill=MH_EQC
  1844. if EleanorEQCLevel==nil then
  1845. level=5
  1846. else
  1847. level=EleanorEQCLevel
  1848. end
  1849. end
  1850. elseif MySpheres >= AutoComboSpheres then
  1851. skill=MH_TINDER_BREAKER
  1852. if EleanorTinderBreakerLevel==nil then
  1853. level=5
  1854. else
  1855. level=EleanorTinderBreakerLevel
  1856. end
  1857. end
  1858. end
  1859. end
  1860. if level ~=0 then
  1861. return skill,level
  1862. end
  1863. end
  1864. return 0,0
  1865. end
  1866.  
  1867. function GetAtkSkill(myid)
  1868. local skill = 0
  1869. local level = 0
  1870. if (IsHomun(myid)==1) then
  1871. htype=GetV(V_HOMUNTYPE,myid)
  1872. if htype < 17 then
  1873. homuntype=modulo(GetV(V_HOMUNTYPE,myid),4)
  1874. else
  1875. homuntype=modulo(OldHomunType,4)
  1876. end
  1877. if (homuntype==0) then -- It's a vani!
  1878. skill=HVAN_CAPRICE
  1879. if GetTick() < AutoSkillCooldown[skill] then
  1880. level=0
  1881. skill=0
  1882. elseif (VanCapriceLevel==nil) then
  1883. level=5
  1884. else
  1885. level=VanCapriceLevel
  1886. end
  1887. elseif (homuntype==3) then -- It's a filer!
  1888. skill=HFLI_MOON
  1889. if GetTick() < AutoSkillCooldown[skill] then
  1890. level=0
  1891. skill=0
  1892. elseif (FilerMoonlightLevel==nil) then
  1893. level=5
  1894. else
  1895. level=FilerMoonlightLevel
  1896. end
  1897. end
  1898. if level ~=0 then
  1899. return skill,level
  1900. end
  1901. else
  1902. for i,v in ipairs(AtkSkillList) do
  1903. level = SkillList[MercType][v]
  1904. if level ~= nil then
  1905. skill=v
  1906. return skill,level
  1907. end
  1908. end
  1909. end
  1910. return 0,0
  1911. end
  1912.  
  1913. function GetPushbackSkill(myid)
  1914. if (IsHomun(myid)==1) then
  1915. return 0,0
  1916. else
  1917. for i,v in ipairs(PushSkillList) do
  1918. level = SkillList[MercType][v]
  1919. if level ~= nil then
  1920. skill=v
  1921. return skill,level
  1922. end
  1923. end
  1924. end
  1925. return 0,0
  1926. end
  1927.  
  1928.  
  1929. function GetDebuffSkill(myid)
  1930. if (IsHomun(myid)==1) then
  1931. if GetV(V_HOMUNTYPE,MyID)==EIRA and UseEiraSilentBreeze==1 then
  1932. skill=MH_SILENT_BREEZE
  1933. if EiraSilentBreezeLevel==nil then
  1934. level=5
  1935. else
  1936. level=EiraSilentBreezeLevel
  1937. end
  1938. return skill,level
  1939. elseif GetV(V_HOMUNTYPE,MyID)==DIETER and UseDieterVolcanicAsh==1 then
  1940. skill=MH_VOLCANIC_ASH
  1941. level=5
  1942. local t = GetTick()
  1943. if (AshTimeout[1] < t or AshTimeout[2] < t or AshTimeout[3] < t) then
  1944. return skill,level
  1945. else
  1946. return 0,0
  1947. end
  1948. end
  1949. else
  1950. for i,v in ipairs(DebuffSkillList) do
  1951. level = SkillList[MercType][v]
  1952. if level ~= nil then
  1953. skill=v
  1954. return skill,level
  1955. end
  1956. end
  1957. end
  1958. return 0,0
  1959. end
  1960.  
  1961. function GetMinionSkill(myid)
  1962. local level,skill=0,0
  1963. if (IsHomun(myid)==1) then
  1964. if GetV(V_HOMUNTYPE,MyID)==SERA and UseSeraCallLegion==1 then
  1965. skill=MH_SUMMON_LEGION
  1966. TraceAI("GetMinionSkill"..skill)
  1967. if SeraCallLegionLevel == nil then
  1968. level=5
  1969. elseif SeraCallLegionLevel < 1 then
  1970. skill,level=0,0
  1971. elseif SeraCallLegionLevel > 5 then
  1972. level=5
  1973. else
  1974. level=SeraCallLegionLevel
  1975. end
  1976. TraceAI("GetMinionSkill "..skill..level)
  1977. if AutoSkillCooldown[skill]~=nil then
  1978. if GetTick() < AutoSkillCooldown[skill] then -- in cooldown
  1979. level=0
  1980. skill=0
  1981. end
  1982. end
  1983. return skill,level
  1984. end
  1985. end
  1986. return 0,0
  1987. end
  1988.  
  1989. function GetProvokeSkill(myid)
  1990. if (IsHomun(myid)==1) then
  1991. return 0,0
  1992. else
  1993. level=SkillList[MercType][MER_PROVOKE]
  1994. if level ~=nil then
  1995. return MER_PROVOKE,level
  1996. end
  1997. end
  1998. return 0,0
  1999. end
  2000.  
  2001. function GetSacrificeSkill(myid)
  2002. level=SkillList[MercType][ML_DEVOTION]
  2003. if level ~=nil then
  2004. return ML_DEVOTION,level
  2005. end
  2006. return 0,0
  2007. end
  2008.  
  2009. function GetMobSkill(myid)
  2010. local skill = 0
  2011. local level = 0
  2012. if (IsHomun(myid)==1) then
  2013.  
  2014. htype=GetV(V_HOMUNTYPE,MyID)
  2015. if htype <17 then
  2016. skill=0
  2017. else -- it's a homun s
  2018. if htype==EIRA and UseEiraXenoSlasher==1 then
  2019. skill=MH_XENO_SLASHER
  2020. if EiraXenoSlasherLevel==nil then
  2021. level=4
  2022. else
  2023. level=EiraXenoSlasherLevel
  2024. end
  2025. elseif htype==BAYERI and UseBayeriHailegeStar==1 then
  2026. skill=MH_HEILIGE_STANGE
  2027. if BayeriHailegeStarLevel==nil then
  2028. level=5
  2029. else
  2030. level=BayeriHailegeStarLevel
  2031. end
  2032. elseif htype==SERA and UseSeraPoisonMist==1 and PoisonMistMode==0 then
  2033. skill=MH_POISON_MIST
  2034. if SeraPoisonMistLevel==nil then
  2035. level=5
  2036. else
  2037. level=SeraPoisonMistLevel
  2038. end
  2039. elseif htype==DIETER and UseDieterLavaSlide==1 and LavaSlideMode==0 then
  2040. skill=MH_LAVA_SLIDE
  2041. if DieterLavaSlideLevel==nil then
  2042. level=5
  2043. else
  2044. level=DieterLavaSlideLevel
  2045. end
  2046. end
  2047. if AutoSkillCooldown[skill]~=nil then
  2048. if GetTick() < AutoSkillCooldown[skill] then -- in cooldown
  2049. level=0
  2050. skill=0
  2051. end
  2052. end
  2053. end
  2054. return skill,level
  2055. else -- SO MUCH EASIER WHEN LEVEL ISN'T SELECTABLE!!!!
  2056. for i,v in ipairs(MobSkillList) do
  2057. level = SkillList[MercType][v]
  2058. if level ~= nil then
  2059. skill=v
  2060. return skill,level
  2061. end
  2062. end
  2063. end
  2064. return 0,0
  2065. end
  2066.  
  2067.  
  2068. function GetQuickenSkill(myid)
  2069. local level = 0
  2070. local skill = 0
  2071. if (IsHomun(myid)==1) then
  2072. htype=GetV(V_HOMUNTYPE,myid)
  2073. if htype < 17 then
  2074. homuntype=modulo(GetV(V_HOMUNTYPE,myid),4)
  2075. else
  2076. homuntype=modulo(OldHomunType,4)
  2077. end
  2078. if (homuntype==1) then -- It's a lif!
  2079. skill=HLIF_CHANGE
  2080. level=3
  2081. elseif (homuntype==3) then -- It's a filer!
  2082. skill=HFLI_FLEET
  2083. if (FilirFlitLevel==nil) then
  2084. level=5
  2085. else
  2086. level=FilirFlitLevel
  2087. end
  2088. elseif (homuntype==2) then --it's an amistr
  2089. skill=HAMI_BLOODLUST
  2090. level=3
  2091. end
  2092. else
  2093. level=SkillList[MercType][MER_QUICKEN]
  2094. if level ~=nil then
  2095. skill=MER_QUICKEN
  2096. end
  2097. end
  2098. if AutoSkillCooldown[skill]~=nil then
  2099. if GetTick() < AutoSkillCooldown[skill] then -- in cooldown
  2100. level=0
  2101. skill=0
  2102. end
  2103. end
  2104. return skill,level
  2105. end
  2106.  
  2107. function GetSOffensiveSkill(myid)
  2108. local level = 0
  2109. local skill = 0
  2110. local skillopt = 0
  2111. if (IsHomun(myid)==1) then
  2112. htype=GetV(V_HOMUNTYPE,myid)
  2113. if (htype==BAYERI and UseBayeriAngriffModus~=0) then
  2114. skill=MH_ANGRIFFS_MODUS
  2115. level = 5
  2116. skillopt=UseBayeriAngriffModus
  2117. elseif (htype==DIETER and UseDieterMagmaFlow~=0) then
  2118. skill=MH_MAGMA_FLOW
  2119. level = 5
  2120. skillopt=UseDieterMagmaFlow
  2121. end
  2122. return skill,level,skillopt
  2123. else
  2124. level=SkillList[MercType][MER_BLESSING]
  2125. if level~=nil then
  2126. skill=MER_BLESSING
  2127. else
  2128. level=0
  2129. end
  2130. return skill,level,UseBlessingSelf
  2131. end
  2132. end
  2133.  
  2134. function GetSDefensiveSkill(myid)
  2135. local level = 0
  2136. local skill = 0
  2137. local skillopt=0
  2138. if (IsHomun(myid)==1) then
  2139. htype=GetV(V_HOMUNTYPE,myid)
  2140. if (htype==BAYERI and UseBayeriGoldenPherze~=0) then
  2141. skill=MH_GOLDENE_FERSE
  2142. level = 5
  2143. skillopt=UseBayeriGoldenPherze
  2144. elseif (htype==DIETER and UseDieterGraniticArmor~=0) then
  2145. skill=MH_GRANITIC_ARMOR
  2146. level = 5
  2147. skillopt=UseDieterGraniticArmor
  2148. end
  2149. return skill,level,skillopt
  2150. else
  2151. level=SkillList[MercType][MER_KYRIE]
  2152. if level~=nil then
  2153. skill=MER_KYRIE
  2154. else
  2155. level=0
  2156. end
  2157. return skill,level,UseKyrieSelf
  2158. end
  2159. return 0,0,0
  2160. end
  2161.  
  2162. function GetSOwnerBuffSkill(myid)
  2163. local level = 0
  2164. local skill = 0
  2165. local skillopt = 0
  2166. if (IsHomun(myid)==1) then
  2167. htype=GetV(V_HOMUNTYPE,myid)
  2168. if (htype==EIRA and UseEiraOveredBoost~=0) then
  2169. skill=MH_OVERED_BOOST
  2170. level = 5
  2171. skillopt=UseEiraOveredBoost
  2172. elseif (htype==DIETER and UseDieterPyroclastic~=0) then
  2173. skill=MH_PYROCLASTIC
  2174. level = 5
  2175. skillopt=UseDieterPyroclastic
  2176. end
  2177. return skill,level,skillopt
  2178. else
  2179. level=SkillList[MercType][MER_INCAGI]
  2180. if level~=nil then
  2181. skill=MER_INCAGI
  2182. else
  2183. level=0
  2184. end
  2185. return skill,level,UseIncAgiSelf
  2186. end
  2187. return 0,0,0
  2188. end
  2189.  
  2190. function GetSightOrAoE(myid)
  2191. local level = 0
  2192. local skill = 0
  2193. local skillopt = 0
  2194. if (IsHomun(myid)==1) then
  2195. htype=GetV(V_HOMUNTYPE,myid)
  2196. if (htype==DIETER and UseDieterLavaSlide==1 and LavaSlideMode~=0) then
  2197. skill=MH_LAVA_SLIDE
  2198. level = 5
  2199. skillopt=LavaSlideMode
  2200. elseif (htype==SERA and PoisonMistMode~=0 and UseSeraPoisonMist==1) then
  2201. skill=MH_POISON_MIST
  2202. level = 5
  2203. skillopt=PoisonMistMode
  2204. end
  2205. else
  2206. if MercType==2 then
  2207. skill=MER_SIGHT
  2208. level=1
  2209. skillopt=UseAutoSight
  2210. end
  2211. end
  2212. if AutoSkillCooldown[skill]~=nil then
  2213. if GetTick() < AutoSkillCooldown[skill] then -- in cooldown
  2214. level=0
  2215. skill=skill
  2216. end
  2217. end
  2218. return skill,level,skillopt
  2219. end
  2220. function GetGuardSkill(myid)
  2221. local level = 0
  2222. local skill = 0
  2223. if (IsHomun(myid)==1) then
  2224. htype=GetV(V_HOMUNTYPE,myid)
  2225. if htype < 17 then
  2226. homuntype=modulo(GetV(V_HOMUNTYPE,myid),4)
  2227. else
  2228. homuntype=modulo(OldHomunType,4)
  2229. end
  2230. if (homuntype==1) then -- It's a lif!
  2231. skill=HLIF_AVOID
  2232. if (LifEscapeLevel==nil) then
  2233. level=5
  2234. else
  2235. level=LifEscapeLevel
  2236. end
  2237. elseif (homuntype==2) then -- It's an amistr!
  2238. skill=HAMI_DEFENCE
  2239. if (AmiBulwarkLevel==nil) then
  2240. level=5
  2241. else
  2242. level=AmiBulwarkLevel
  2243. end
  2244. elseif (homuntype==3) then -- It's an filir!
  2245. skill=HFLI_SPEED
  2246. if (FilirAccelLevel==nil) then
  2247. level=5
  2248. else
  2249. level=FilirAccelLevel
  2250. end
  2251. end
  2252. return skill,level
  2253. else
  2254. for i,v in ipairs(GuardSkillList) do
  2255. level = SkillList[MercType][v]
  2256. if level ~= nil then
  2257. skill=v
  2258. return skill,level
  2259. end
  2260. end
  2261. end
  2262. return 0,0
  2263. end
  2264.  
  2265. function GetOffensiveOwnerSkill(myid)
  2266. local level = 0
  2267. local skill = 0
  2268. local skillopt = 0
  2269. if (IsHomun(myid)==1) then
  2270. return 0,0,0
  2271. else
  2272. level=SkillList[MercType][MER_BLESSING]
  2273. if level~=nil then
  2274. skill=MER_BLESSING
  2275. else
  2276. level=0
  2277. end
  2278. return skill,level,UseBlessingOwner
  2279. end
  2280. end
  2281. function GetDefensiveOwnerSkill(myid)
  2282. local level = 0
  2283. local skill = 0
  2284. local skillopt = 0
  2285. if (IsHomun(myid)==1) then
  2286. if GetV(V_HOMUNTYPE,MyID)==SERA and UseSeraPainkiller~=0 then
  2287. level=5
  2288. return MH_PAIN_KILLER,level,UseSeraPainkiller
  2289. else
  2290. return 0,0,0
  2291. end
  2292. else
  2293. level=SkillList[MercType][MER_KYRIE]
  2294. if level~=nil then
  2295. skill=MER_KYRIE
  2296. else
  2297. level=0
  2298. end
  2299. return skill,level,UseKyrieOwner
  2300. end
  2301. end
  2302. function GetOtherOwnerSkill(myid)
  2303. local level = 0
  2304. local skill = 0
  2305. local skillopt = 0
  2306. if (IsHomun(myid)==1) then
  2307. return 0,0,0
  2308. else
  2309. level=SkillList[MercType][MER_INCAGI]
  2310. if level~=nil then
  2311. skill=MER_INCAGI
  2312. else
  2313. level=0
  2314. end
  2315. return skill,level,UseIncAgiOwner
  2316. end
  2317. end
  2318.  
  2319.  
  2320.  
  2321. function GetHealingSkill(myid)
  2322. local level = 0
  2323. local skill = 0
  2324. if (IsHomun(myid)==1) then
  2325. htype=GetV(V_HOMUNTYPE,myid)
  2326. if htype < 17 then --if it's not a homun S just run it through modulo.
  2327. homuntype=modulo(GetV(V_HOMUNTYPE,myid),4)
  2328. else --If it's a homun S, get the OldHomunType
  2329. if homuntype == EIRA and HealOwnerBreeze == 1 then --Handling for Eira silent breeze
  2330. skill=MH_SILENT_BREEZE
  2331. if GetTick() < AutoSkillCooldown[skill] then
  2332. level=0
  2333. else
  2334. level=5
  2335. end
  2336. return skill,level
  2337. end
  2338. homuntype=modulo(OldHomunType,4)
  2339. end
  2340. if (homuntype==1) then -- It's a lif
  2341. skill=HLIF_HEAL
  2342. if GetTick() < AutoSkillCooldown[skill] then
  2343. level=0
  2344. elseif (LifHealLevel==nil) then
  2345. level=5
  2346. else
  2347. level=LifHealLevel
  2348. end
  2349. elseif homuntype==0 then -- It's a vani
  2350. skill=HVAN_CHAOTIC
  2351. if GetTick() < AutoSkillCooldown[skill] then
  2352. level=0
  2353. elseif (VaniChaoticLevel==nil) then
  2354. level=3
  2355. else
  2356. level=VaniChaoticLevel
  2357. end
  2358. end
  2359. else
  2360. --currently no merc healing skills
  2361. end
  2362. return skill,level
  2363. end
  2364.  
  2365. function GetSnipeSkill(myid)
  2366. return GetAtkSkill(myid)
  2367. end
  2368.  
  2369. function GetTargetedSkills(myid)
  2370. s,l=GetAtkSkill(myid)
  2371. Mainatk={MAIN_ATK,s,l}
  2372. s,l=GetSAtkSkill(myid)
  2373. Satk={S_ATK,s,l}
  2374. s,l=GetComboSkill(myid)
  2375. ComboAtk={COMBO_ATK,s,l}
  2376. s,l=GetGrappleSkill(myid)
  2377. GrappleAtk={GRAPPLE_ATK,s,l}
  2378. s,l=GetMobSkill(myid)
  2379. Mobatk={MOB_ATK,s,l}
  2380. s,l=GetDebuffSkill(myid)
  2381. Debuffatk={DEBUFF_ATK,s,l}
  2382. s,l=GetMinionSkill(myid)
  2383. Minionatk={MINION_ATK,s,l}
  2384. result={Mainatk,Satk,ComboAtk,GrappleAtk,Mobatk,Debuffatk,Minionatk}
  2385. return result
  2386. end
  2387.  
  2388. function GetSkillInfo(skill,info,level)
  2389. if skill~=nil and info~=nil then
  2390. if SkillInfo[skill]~=nil then
  2391. local t=SkillInfo[skill][info]
  2392. if t~=nil then
  2393. if level ==nil and type(t)=="table" then
  2394. logappend("AAI_ERROR","Attempted to call GetSkillInfo() with only 2 arguments "..skill.." "..info)
  2395. if type(t)~="table" and t~=nil then
  2396. return t
  2397. else
  2398. return -1
  2399. end
  2400. elseif type(t)~="table" then
  2401. return t
  2402. elseif SkillInfo[skill][info][level]~=nil then
  2403. return SkillInfo[skill][info][level]
  2404. else
  2405. logappend("AAI_ERROR","GetSkillInfo(): No skill info type "..info.." found for this level "..FormatSkill(skill,level))
  2406. if info==2 then
  2407. local r=0
  2408. if (_VERSION=="Lua 5.1") then
  2409. r=GetV(V_SKILLATTACKRANGE_LEVEL,MyID,skill,level)
  2410. else
  2411. r=GetV(V_SKILLATTACKRANGE,MyID,skill)
  2412. end
  2413. logappend("AAI_ERROR","GetSkillInfo(): Range for unknown skill requested, returning builtin value"..r.." "..skill)
  2414. return r
  2415. elseif SkillInfo[skill][info][1]~= nil then
  2416. return SkillInfo[skill][info][1]
  2417. else
  2418. return 0
  2419. end
  2420. end
  2421. else
  2422. logappend("AAI_ERROR","GetSkillInfo(): No skill info type "..info.." found for this skill "..FormatSkill(skill,level).." called by ")
  2423. if info==2 then
  2424. logappend("AAI_ERROR","GetSkillInfo(): Range for unknown skill requested, returning builtin value"..GetV(V_SKILLATTACKRANGE,MyID,skill))
  2425. return GetV(V_SKILLATTACKRANGE,MyID,skill)
  2426. elseif info==7 then
  2427. return 1
  2428. else
  2429. return 0
  2430. end
  2431. end
  2432. else
  2433. logappend("AAI_ERROR","GetSkillInfo(): No skill info found for this skill "..FormatSkill(skill,level).." info type requested "..info)
  2434. if info==2 then
  2435. logappend("AAI_ERROR","GetSkillInfo(): Range for unknown skill requested, returning builtin value"..GetV(V_SKILLATTACKRANGE,MyID,skill))
  2436. return GetV(V_SKILLATTACKRANGE,MyID,skill)
  2437. elseif info==7 then
  2438. return 1
  2439. else
  2440. return 0
  2441. end
  2442. end
  2443. else
  2444. if skill==nil then
  2445. skill="nil"
  2446. end
  2447. if level==nil then
  2448. level="nil"
  2449. end
  2450. if info==nil then
  2451. info="nil"
  2452. end
  2453. logappend("AAI_ERROR","GetSkillInfo(): Invalid arguments - skill="..skill.." level="..level.." info="..info)
  2454. return 0
  2455. end
  2456. end
  2457. --#######################
  2458. --### Other Functions ###
  2459. --#######################
  2460.  
  2461. function KiteOK(myid)
  2462. mertype=GetV(V_MERTYPE,myid)
  2463. if (mertype==nil) then
  2464. homuntype=modulo(GetV(V_HOMUNTYPE,myid),4)
  2465. if ((homuntype==0 or homuntype==3 )and DoNotChase==1) then
  2466. return 1
  2467. else
  2468. return 0
  2469. end
  2470. elseif (mertype < 11) then
  2471. return 1
  2472. else
  2473. return 0
  2474. end
  2475. end
  2476.  
  2477. function DoSkill(skill,level,target,mode,targx,targy)
  2478. TraceAI("doskill called skill:"..skill.."level:"..level.."target"..target)
  2479. if skill==0 or level==0 or skill==nil or level==nil then
  2480. logappend("AAI_ERROR","doskill called skill:"..skill.."level:"..level.."target"..target.."mode"..mode.."state "..MyState.."pstate "..MyPState)
  2481. return 0
  2482. end
  2483. targetmode=GetSkillInfo(skill,7)
  2484. if skill==HFLI_SBR44 and AllowSBR44~=1 then
  2485. logappend("AAI_ERROR","Attempt to use SBR 44 blocked. If you really want to use this, set AllowSBR44 = 1 in H_Extra")
  2486. elseif targetmode==0 then
  2487. SkillObject(MyID,level,skill,MyID)
  2488. elseif targetmode==1 then
  2489. SkillObject(MyID,level,skill,target)
  2490. elseif targetmode==2 then
  2491. if targx == nil then
  2492. x,y=GetV(V_POSITION,target)
  2493. SkillGround(MyID,level,skill,x,y)
  2494. else
  2495. SkillGround(MyID,level,skill,targx,targy)
  2496. end
  2497. end
  2498. if mode~=nil then
  2499. if mode > 0 then
  2500. CastSkillMode=mode
  2501. CastSkill=skill
  2502. CastSkillLevel=level
  2503. CastSkillTime=GetTick()
  2504. CastSkillState=0
  2505. logappend("AAI_SKILLFAIL", "Mode set "..mode.." skill "..skill.." level "..level)
  2506. else --mode is negative, call the plugin mode handler.
  2507. DoSkillHandleMode(skill,level,target,mode,targx,targy)
  2508. logappend("AAI_SKILLFAIL", "Mode set "..mode.." skill "..skill.." level "..level)
  2509. end
  2510. end
  2511. local t=GetTick();
  2512. delay=AutoSkillDelay + GetSkillInfo(skill,4,level)+GetSkillInfo(skill,5,level)*CastTimeRatio
  2513. AutoSkillCastTimeout=delay+t
  2514. if AutoSkillCooldown[skill]~=nil then
  2515. AutoSkillCooldown[skill]=t+GetSkillInfo(skill,9,level)+delay
  2516. elseif (skill==MH_VOLCANIC_ASH) then --handle the three ash timeouts
  2517. if (AshTimeout[1] < t) then
  2518. AshTimeout[1]=t+GetSkillInfo(skill,9,level)+delay
  2519. elseif (AshTimeout[2] < t) then
  2520. AshTimeout[2]=t+GetSkillInfo(skill,9,level)+delay
  2521. else
  2522. AshTimeout[3]=t+GetSkillInfo(skill,9,level)+delay
  2523. end
  2524. end
  2525. delay = delay + GetSkillInfo(skill,6,level)
  2526. AutoSkillTimeout=t+delay
  2527. if AutoSkillCooldown[skill]~=nil then
  2528. TraceAI("DoSkill: "..skill.." level:"..level.." target:"..target.." mode:"..targetmode.." delay "..delay.." cooldown: "..AutoSkillCooldown[skill]-GetTick())
  2529. else
  2530. TraceAI("DoSkill: "..skill.." level:"..level.." target:"..target.." mode:"..targetmode.." delay "..delay)
  2531. end
  2532. if skill==MH_MIDNIGHT_FRENZY then
  2533. MySpheres = math.max(0,MySpheres - 2)
  2534. ComboSVTimeout=0
  2535. UpdateTimeoutFile()
  2536. elseif skill==MH_SILVERVEIN_RUSH then
  2537. ComboSVTimeout=GetTick()+2000
  2538. ComboSCTimeout=0
  2539. MySpheres = math.max(0,MySpheres - 1)
  2540. UpdateTimeoutFile()
  2541. elseif skill==MH_SONIC_CRAW then
  2542. ComboSCTimeout=GetTick()+2000
  2543. ComboSVTimeout=0
  2544. elseif skill==MH_TINDER_BREAKER then
  2545. ComboSCTimeout=GetTick()+2000
  2546. ComboSVTimeout=0
  2547. MySpheres = math.max(0,MySpheres - 1)
  2548. elseif skill==MH_CBC then
  2549. ComboSVTimeout=GetTick()+2000
  2550. ComboSCTimeout=0
  2551. MySpheres = math.max(0,MySpheres - 1)
  2552. elseif skill==MH_EQC then
  2553. ComboSVTimeout=0
  2554. ComboSCTimeout=0
  2555. --No sphere use?
  2556. else --Combo wasn't used, so kill the timeouts
  2557. ComboSCTimeout=0
  2558. ComboSVTimeout=0
  2559. end
  2560.  
  2561. TraceAI("DoSkill: "..skill.." level:"..level.." target:"..target.." mode:"..targetmode.." delay "..delay)
  2562. logappend("AAI_SKILLFAIL", "DoSkill: "..skill.." level:"..level.." target:"..target.." mode:"..targetmode.." delay "..delay)
  2563. return
  2564. end
  2565.  
  2566. function modtwroSend()
  2567. if modtwROSkillGroundID~=0 then
  2568. logappend("AAI_Lag","Calling skillground function")
  2569. OldSkillGround(MyID,modtwROSkillGroundLV,modtwROSkillGroundID,modtwROSkillGroundX,modtwROSkillGroundY)
  2570. LagReductionCD=LagReduction
  2571. elseif modtwROSkillObjectID~=0 then
  2572. logappend("AAI_Lag","Calling SkillObject function")
  2573. OldSkillObject(MyID,modtwROSkillObjectLV,modtwROSkillObjectID,modtwROSkillObjectTarg)
  2574. LagReductionCD=LagReduction
  2575. else
  2576. if modtwRODidMove==0 then
  2577. if modtwROMoveX~=0 then
  2578. logappend("AAI_Lag","Calling Move function, didmove=0")
  2579. OldMove(MyID,modtwROMoveX,modtwROMoveY)
  2580. LagReductionCD=LagReduction
  2581. modtwRODidMove=1
  2582. modtwRODidAttack=0
  2583. end
  2584. else
  2585. modtwRODidMove=0
  2586. end
  2587. if modtwRODidAttack==0 then
  2588. if modtwROAttackTarget~=0 then
  2589. logappend("AAI_Lag","Calling attack function, didattack=0")
  2590. OldAttack(MyID,modtwROAttackTarget)
  2591. LagReductionCD=LagReduction
  2592. modtwRODidAttack=1
  2593. end
  2594. else
  2595. modtwRODidAttack=0
  2596. end
  2597. end
  2598. modtwROSkillGroundLV,modtwROSkillGroundID,modtwROSkillGroundX,modtwROSkillGroundY,modtwROSkillObjectLV,modtwROSkillObjectID,modtwROSkillObjectTarg,modtwROAttackTarget=0,0,0,0,0,0,0,0
  2599. modtwROAttackTarget,modtwROMoveX,modtwROMoveY=0,0,0
  2600. end
  2601.  
  2602.  
  2603.  
  2604.  
  2605.  
  2606.  
  2607.  
  2608.  
  2609. -- I SHOULDNT HAVE TO CODE THIS!
  2610. function modulo(a,b)
  2611. return a-math.floor(a/b)*b
  2612. end
  2613. -- OR THIS!
  2614. function len(listin)
  2615. local length=0
  2616. for k,v in pairs(listin) do
  2617. length = length + 1
  2618. end
  2619. return length
  2620. end
  2621.  
  2622. function absceil(x)
  2623. if x>0 then
  2624. return math.ceil(x)
  2625. else
  2626. return math.floor(x)
  2627. end
  2628. end
  2629.  
  2630. function absunit(x)
  2631. if x==0 then
  2632. return 0
  2633. elseif x > 0 then
  2634. return 1
  2635. else -- x < 0
  2636. return -1
  2637. end
  2638. end
  2639.  
  2640.  
  2641. -- Logging functions:
  2642.  
  2643. function FormatSkill(skill,level)
  2644. if skill==nil then
  2645. return "nil skill"
  2646. end
  2647. local output
  2648. local name
  2649. if SkillInfo[skill]==nil then
  2650. name=skill
  2651. elseif SkillInfo[skill][1]==nil then
  2652. name=skill
  2653. else
  2654. name=SkillInfo[skill][1]
  2655. end
  2656. output = name.." ("..skill..")"
  2657. if level == nil then
  2658. return output
  2659. else
  2660. return output.." level "..level
  2661. end
  2662. end
  2663.  
  2664. function FormatMotion(motion)
  2665. if motion==0 then
  2666. return "Standing ("..motion..")"
  2667. elseif motion==1 then
  2668. return "Moving ("..motion..")"
  2669. elseif motion==2 or motion==9 then
  2670. return "Attacking ("..motion..")"
  2671. elseif motion==3 then
  2672. return "Dead ("..motion..")"
  2673. elseif motion==4 then
  2674. return "Flinching ("..motion..")"
  2675. elseif motion==5 then
  2676. return "Bending over ("..motion..")"
  2677. elseif motion==6 then
  2678. return "Sitting ("..motion..")"
  2679. elseif motion==7 then
  2680. return "Using skill ("..motion..")"
  2681. elseif motion==8 then
  2682. return "Casting ("..motion..")"
  2683. else
  2684. return motion
  2685. end
  2686. end
  2687.  
  2688. function formatval (val)
  2689. if val == nil then
  2690. return "nil"
  2691. elseif type(val)=="string" then
  2692. return "'"..val.."'"
  2693. elseif type(val)=="function" then
  2694. return "function"
  2695. end
  2696. return val
  2697. end
  2698.  
  2699. function logappend (filename,message)
  2700. if LogEnable[filename]==1 then
  2701. TraceAI("Logging "..filename.." - "..message)
  2702. outfile = io.open("./"..filename..".log", "a")
  2703. outfile:seek("end")
  2704. if filename=="AAI_SKILLFAIL" then
  2705. outfile:write(os.date("%c").." ("..GetTick()..") "..TypeString..MyState.."\t"..message.."\n")
  2706. else
  2707. outfile:write(os.date("%c").." "..TypeString..MyState.."\t"..message.."\n")
  2708. end
  2709. outfile:close()
  2710. end
  2711. end
  2712.  
  2713. function formatmypos(steps)
  2714. if steps>10 then
  2715. logappend("AAI_ERROR","Invalid number of steps called for formatmypos() "..steps)
  2716. steps=10
  2717. elseif steps <1 then
  2718. logappend("AAI_ERROR","Invalid number of steps called for formatmypos() "..steps)
  2719. steps=1
  2720. end
  2721. local outstring=""
  2722. for v=1,steps,1 do
  2723. outstring=outstring.."("..MyPosX[v]..","..MyPosY[v]..")"
  2724. if v~=step then
  2725. outstring=outstring..","
  2726. end
  2727. end
  2728. return outstring
  2729. end
  2730.  
  2731. function formatpos(x,y)
  2732. return x..","..y
  2733. end
  2734. --------------------------------------------
  2735. -- List utility
  2736. --------------------------------------------
  2737. List = {}
  2738.  
  2739. function List.new ()
  2740. return { first = 0, last = -1}
  2741. end
  2742.  
  2743. function List.pushleft (list, value)
  2744. local first = list.first-1
  2745. list.first = first
  2746. list[first] = value;
  2747. end
  2748.  
  2749. function List.pushright (list, value)
  2750. local last = list.last + 1
  2751. list.last = last
  2752. list[last] = value
  2753. end
  2754.  
  2755. function List.popleft (list)
  2756. local first = list.first
  2757. if first > list.last then
  2758. return nil
  2759. end
  2760. local value = list[first]
  2761. list[first] = nil -- to allow garbage collection
  2762. list.first = first+1
  2763. return value
  2764. end
  2765.  
  2766. function List.popright (list)
  2767. local last = list.last
  2768. if list.first > last then
  2769. return nil
  2770. end
  2771. local value = list[last]
  2772. list[last] = nil
  2773. list.last = last-1
  2774. return value
  2775. end
  2776.  
  2777. function List.clear (list)
  2778. for i,v in ipairs(list) do
  2779. list[i] = nil
  2780. end
  2781. --[[
  2782. if List.size(list) == 0 then
  2783. return
  2784. end
  2785. local first = list.first
  2786. local last = list.last
  2787. for i=first, last do
  2788. list[i] = nil
  2789. end
  2790. --]]
  2791. list.first = 0
  2792. list.last = -1
  2793. end
  2794.  
  2795. function List.size (list)
  2796. local size = list.last - list.first + 1
  2797. return size
  2798. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement