From 5dbeeab3a7ce4199bf799c2f084d7ce309f1906d Mon Sep 17 00:00:00 2001
From: DarkGod <darkgod@net-core.org>
Date: Tue, 12 Nov 2019 20:37:58 +0100
Subject: [PATCH] predator

---
 game/modules/tome/class/Player.lua            |  11 ++--
 game/modules/tome/data/damage_types.lua       |  14 ++----
 .../shockbolt/terrain/spell_stonewall_01.png  | Bin 0 -> 11021 bytes
 .../tome/data/talents/cursed/predator.lua     |  47 +++++++++++-------
 .../modules/tome/data/timed_effects/other.lua |  38 +++++++-------
 5 files changed, 57 insertions(+), 53 deletions(-)
 create mode 100644 game/modules/tome/data/gfx/shockbolt/terrain/spell_stonewall_01.png

diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua
index 149d0aec5b..b47bc0ede7 100644
--- a/game/modules/tome/class/Player.lua
+++ b/game/modules/tome/class/Player.lua
@@ -625,17 +625,16 @@ function _M:playerFOV()
 	end
 
 	--Handle Mark Prey Vision
-	if self:knowTalent(self.T_MARK_PREY) then
-		local t = self:getTalentFromId(self.T_MARK_PREY)
-		for i = 1, t.getCount(self, t) do
-			local e = table.get(self, "marked_prey_tbl", i)
-			if e then
+	if self:hasEffect(self.EFF_PREDATOR) then
+		local uid, e = next(game.level.entities)
+		while uid do
+			if e.marked_prey then
 				game.level.map.seens(e.x, e.y, 0.6)
 			end
+			uid, e = next(game.level.entities, uid)
 		end
 	end
 
-
 	if self:knowTalent(self.T_SHADOW_SENSES) then
 		local t = self:getTalentFromId(self.T_SHADOW_SENSES)
 		local range = self:getTalentRange(t)
diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua
index 89186247a8..deccc1ffab 100644
--- a/game/modules/tome/data/damage_types.lua
+++ b/game/modules/tome/data/damage_types.lua
@@ -457,19 +457,13 @@ setDefaultProjector(function(src, x, y, type, dam, state)
 		end
 
 		-- Mark Prey: reduces damage from subtype of marked prey
-		if target.knowTalent and target:knowTalent(target.T_MARK_PREY) and src.subtype then
-			local tMarkPrey = target:getTalentFromId(target.T_MARK_PREY)
-			for i = 1, tMarkPrey.getCount(target, tMarkPrey) do
-				local etype = table.get(target, "mark_prey2", game.level.id, i)
-				if etype and etype == src.subtype then
-					dam = dam * (100 - tMarkPrey.getPower(target, tMarkPrey)) / 100
-					break
-				end
+		if target.hasEffect and target:hasEffect(target.EFF_PREDATOR) and src.subtype then
+			if table.get(target, "mark_prey2", game.level.id, src.subtype) then
+				dam = dam * (100 - target:callTalent(target.T_MARK_PREY, "getPower")) / 100
+				print("[PROJECTOR] predator reduction dam", dam)
 			end
 		end
 
-
-
 		-- Psychic Projection
 		if src.attr and src:attr("is_psychic_projection") and not game.zone.is_dream_scape then
 			if (target.subtype and target.subtype == "ghost") or mind_linked then
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/spell_stonewall_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/spell_stonewall_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..b064dd115c12f05e619d49316d434ed11ec03445
GIT binary patch
literal 11021
zcmbVyRa6|^wr(TA2?@d7HMlm=xVu~9&^R>GSmO`^NzmZ#Zb1{ABoN%4#t9C=-ERJU
z_CEJMoN*p*jZwAMT=jj^=Sz+HpsB8ai$#V7003~66lJylu9E-U7-)Z=6%Otze-~1i
zoFPmHY76tR^nd`QY@k*U8YLG?JBT*K(#Fqy03rqepm;mz8o~_KR7I?zE}WMCU^snU
z-2Sow05J()H%n_L2#m%GV&~urqC0NuqN8!J0nr%<sBx>g$w2HK6yY8a9k{x#HQdP>
zXhSC<P9x?k@>hWi1ZGL&>*DO{DdG#F`<Gskzx#iVx#(#A1%Ww%=>E$oLp4nr8K?(@
zMu1b0!<vVmmqrN4$s@=O<mG=$!^_Ph#KkSd#ly$J%_G7sD8dJ%`S(Tl*P4fot%$a)
z{J(Ael|Xd%FqoSN7nhHZ52p_wC)C4^iw6h<a&hx=@$z!~MR0ifxxy@cIb1#I|D!<`
z;%V*S;0AMmy3+ik(b5X)1q0Fj_4L0&aB)*p`)|drp8rnN-;{CrTDo!ZaB_3Gxcn2>
zztEmAZOH$1<9|eZ>iW4sxU?ajP%jVbzxA-C{}1_Z?*4Z}{{a7bBckEq@V6+I&azNz
zFBga_Oi30*_xBB_jf0Jdu#lCI4WF$QhoCh#goB%#pPK{73$*<!+VVnpg@pNRxcUF1
z=YQh!2nb6F3dl)u^T`PD@W@F?@d`-E^YQ|@`S`fy1%!nD!&P$igju>;L;hpi;jis~
zbN^!h7p{nm2gDKv_0WYvo&VDXn)Xl_)YBg7Mk6EhPt}EKSPUFoZJ<7$tpAkhzoM3f
zcsO`NY~($lE;Rqjvxvk0-~+!PkF}634}^o4$C8(W-;$q)!wP7_!y#;I$uG#wEyyoy
zZB6%YzRmw{{<!`+#r03K{6Ed}pQFDW`Oo&hN8zvV-@^oP{X0P(e@De7$JPk|VCGPg
zmD2TH{GDl31z9j!?E)PKUWspJ@2^yV^*~?A@o;5RD1}}MOBvE8XeOa<;IOnaV14Ew
z*a~g$*1=Cw{6N6^dXR>SBrF6SgARAT=jAVpDKww2L(6~iw_DHMeu40A0}mRvSdeUf
zg3JDBFSmM)iaQ1V48ECdO*y!?0>={gu?1(Cy9fVnGIbf_RR1)z)uIXqZ$yM<m6qG=
zFne4M=1j*jV?PD$%nqI9cU`=8F#a?~;LxVtT0>ap>}~>HEZMxz9`Whf4jyXuix_#H
zZ1&;^J@~kJBUYPOQqg-vVZ>RwdXd2~bayvbLwy#Y@^OP44<JR}R`W;;ZigN@FC0cm
zPBro&JcFhjw^XvL!QRXA6-Ld&qJbLo2P#w38$cwmb8G8t;OlqI38Rj+;0;xZz91>%
z7Bin2(?~u1yfC3I%9|BL%8`xUl!@^>Ivg3~IYq6npSg&FX94yve096e$l(pdHxiP@
zL9!zEz@cXRx_QM{QF=`o{a?XDEd<DGx|ft@4}Rqt63)iAE<$G>l}$Mnh(9GRLsDQp
z$kgodCFpoFd-*Y<!d?d7#m8pBwK~>9pxJtaysk81b9sGFVME_1v-K%@rX{zs(rQb%
z=J%eEdCTnl8&<M}syFOWbUJQ+cg*PB=Z{i5#?+q1$9?^XWX`i9CzrZUgVXFE5@wrv
z%;yvj<X^t1s!jORTxHfQ{nfr=+rg}bbuz0_ukAazLbZ#w8gBEX-!$FPdK5b(U0ICe
zgjr8UXFhh-H^(5^OXqiGZ+MAAP{M5B$XV7L>w6)N^7<0mhKyH7>Ce_j#vHF*%p5%z
z)<sucWU(zN0fL{OF$rIxPWZcM1TEo($1TQC&Up3Of*e@BzmHf<;c|^zHJ(zVXAi>{
zj`anxh1+7>cxTLM>$YI(_y1%e5j>1PGOnoq%>9w^)YO3m?=x4g^Y<`Hcuq)TE1JUH
zX5F_OW;_jbi~uz^UiX0GnbGDaO5kHU9aMS3-rEA_xUkK)i^EF?Q;#7zo<SUen$;!x
zu<Qb$dW@I&lX~<mu+Qu1$b$P;k>s*Sk$AH1d(EEe)=h^j+Jy~NZ0&n;k)5Z~fixSg
zy51R?_%FT$%gvf`<j?za&PA6Tb^69!O&9PQ=VRwjGDOwgi4BE1>FRvSV;igFtVT~4
zXC`-2bQwRB?Cu+(^rQY5n|Ljq0SS)xyur|SO<vVu>{4dOVLm#Rt?pqJP7^jwddxL4
zB_j86T#q#_;<kS4kun@(VyV%1v)Av8m7RZFQ!Y@%^d7SrRbvelbefRLPNw1P8Iy@;
zyqt|rT#g^ZyO}CrsI1_{CW~gquMa2tvI|H{=$VWWVkzO9r%!DkHbN(j5W#x-v>{0`
z#6w<*G+STZRXunR+{65kSyT7tbdacVMpKiAlgEDKIfE}SwF%8*MFlW>dK(-Zcya&K
z>Jt=jC1tpg%hY*13&GaZKZvP&wK`a=v4t~#BHYN}MBn1?OV_4E6Yk5fGpmgTLIU#|
z(^-RRyve9{qwvNFy=gk^Y0ei~7#>5rX#ft);g5j}R9F2T^q$C^zk?>;l^{D`6}zld
zIZizK=)MG09AoF_cUc3UTx*FRk`DTv&S&;%KR^cbhM0YbaxrN#JHINK$YtI#%;;e?
zKGnX&@K@5@UchT{J$d7fe<|Q;q@`HN*t?z2c=|my3Z`$w_I2O_#*@gdghT(zh)7^z
z$--0TL!zvQvagTR+g1#OhZ;C**x>VMsZD-@nMBE?sT}(U8H3T=rv+ddYNxNI2E_?$
zi5)q7fsUIav-G-n+tXU&vtFW6&2r3A(e>P&(t}C*PVkrYHi_h#j|RR^6#avkrkg*!
zo6*89B})f^_Lwnw0U%_lwDF2R%<VyEV|#HyGA-ddsL;ofaZJ^LZ~P`QQK_=p`WLoK
zZ-l~7Ua@+C>l4Hygl!X=4&No*tjS`;s|kLUD|fwGJeb@PC)rQ|r%e88)PvG2?=fyk
zB>6}*)0=0RW{klCHM4i(Up4${9b~Xa;(L0@QT3)@Bv1mD-R+-&yW*AsUp=of=N#N8
z8VVqs4(i!yJ{WNlJuv}H&U8&<r5=oc-EOZnjU|X~EeU$uu?-Mj`kJlp26*nG?KI=3
z3o=jFF*1<z_Fpp;%gLD-8?}!n*O+K?#70M2cPqAy5!bFJ-aD_nP!VJXYa?g9HllKI
zK4;3w6*-&U6xw<itt*ln_<CcKW2)I1`n5zM@Tq>}Hi$W4m5;C(iw8&Ap&{$4E-LB%
zY4Ftb#_YPxp;DtM=aE_~4_yt>%!zr@giL@<CO1?YE-4Ez%Tq0!)w+;N(N3wBCtj><
zWL{rrZdTRzAd>r}6gJr4l@BmOUw-j{i`1g2sZJ@^51%Pvct@oL?y0fT>7|lVnT*tq
zaj3X~X)!afHBk4>ogq%*ywRqiC17i0ZoVBwR94f5<&rH@WCAs$81PYQoG*7l<Bm6T
ztQ^a@T*0Ze?ybX6O$AHH8rf~9t=9_C<au#H`Ln_dL4<WnRpa{Yu3k*dQ8hU4h%ED+
z*m{Jz0wb6`gPGxg%1AfVdIGA*f4Y#jAtl#r>el@!Odtc^d5ZMG7CD<Us+glbcd|Av
zhDke2y$?`Kj1+;|fgXXjnQ#H<M~}oCp!gp4lRBF^Gi&~$Lm85sW}FfAG9ZMVmN4-Z
z386VD*^fCQ>lncqk}z6Uq$6AfU3)a_5Yw0@9SX`W=9AX3yT@<RISqO=eMo*6El%n}
zSuORgoYEy{ae^$_Cl+@Sk#R-=?=;;BUrBifMxuN8xY{dg&6QJAy-!$QaED?95|%{Y
z>xO!FlXG>cue}m6q6fESdK@jjgpeq5V?dgX2lp?eZKoKIX`y9<VjKkDFy)y8LwH9f
z2&&XnzJ*K`+OU9i=YWKTp&FKDF=iOJC>5w>##O2ifgmn*=Y#O(A}%V`)N+VFqc)-d
zpK{LaR1~C1Y_#*@^%kKqEnc(&sG^#w9wPynQ@$EPQ!67{*0_7R7_U8ihW~H^QDnC-
z#ZEt$z7boLbZ+ELkKRIB^Y(a%7oSz$R{^Z4ap{D-5vyY_$JqZIvnn3MK!j;jm!9EW
z=@CzrP=wU1XNrG|Kk|CECZ#2*$ptX3H-r9)efK50HKx?B@R{`Q9Br&cFa5{*La!fE
zW<-sN_6VMhcKjw5Xgc<sWP%^Ha`D`yzb!$EfpkSIG2w3{{!Crx+=4Q2R7(PtL6x(%
z3^c;AQ|WA{7$LktVXz~$_Z|TOET8sRrIci=f7%l`{d}#c;PHDm8}W7PW-UI18O@@U
zIZ`{H(&Pl4;&U&uh%DZHNS@qDx%LUb62ZDD%tiz`A57`dor4LYsKifmV^fBDaH!&M
zTGnfAkF+&6{{k!Vo;lC9v@|U&reWP?c<v5*l+mee*~g8@C2>BmnM$HLCa10mr|XOB
zhobai;L!`ylH!hE<y0jJ-YyrAJDN2Nlz4<CX>Ewfwa=#xaMP*;as!^n@2rxYfV00N
z7&t?ZbRzn<-<|z|M)x3tjY;HNDk@d#YxD>-(~pc34V5Fi$yyHkc#6liku)!X^DNQS
zYfE}&{EH;$`lt>@<xoFJYu0SdMBnV3<d+ygW{$l6>bpyR#@<po3G2P^UoZFzuNJfl
z3wb|AX!csIFAbm{gC~$W7seSojBMF~0WdlSDYP%rox@w};cxsN?ox_qcDA-&uzlvG
z&O60?8J7}ZcH#{~qbXh9D<sqDeA(}Yb`}@E$TsRRZ_~8@8n7sZOR!Z;1SBosGE_67
z&(S^Bp-UhatlG!F^8LMC8K75`4UyEmb`2a6D<I4CHh<PnL@LhHi|OBs+uFV~g<s*b
zR?YG!S#G2|sEU}6KZm|OPsX9FK#HlDqF%k)y13DO=|n*;NvbIqTYH0Sb|b@@*M#q9
zx<M_e;xHh{D7!by9mh`iU5T)lJ&75RRy|G}z?BcL@;)N^$;~v>Sjr0|$Fv7Wsl@)t
z#jny=Pu;~ZgX#zfE})M5@z3ufiDfpe(T2D5tXKL6DPW)leS!UO`;7Dcf?}E&uFYw>
z@T1tp<ueFt-ztIpQunn>Q#BzuPJA~dM}5(7A_Kp?LdVw;1^o~sg&6;fKes;>jOix}
zA=^!9_1^hhFGk19#NeWgpLD|tT|?%kO>N^Pr0L6$JYIP&;Lqk?3xp`YNvt#|8`jMV
z^Y}_$2<H4=`x1?ewz(woI^j>gGt;Kr0`?-NZ@o!W7JH##Qru(gD`Zm7x5sZWI_9^3
z5)%`@{l@=z#6Xh77YvfkW2|C&5dtVM9#L#+&TfoFVNbK2G22=Iy;D|=&^;_UHQtkn
zL-93f0H4Bd6y-DD{9GR#0Vdl>L0%jshEcM?oEx-G&{}oFr}GGtJUnN(0S*EhkmQ=_
z+k6HSBMu^Ng)b$J#(jH6+D2-gTEpSC4ig0doP_hCmd#LGqywTd1iZneUav0Xlay93
zdgfDuB=OM4X)u0tj+CjM9o41I<|9JSHiRWzl_0xFKg-^k&)dT=>Fx?&%>wNe%^ntM
zmUj&4y9%GOe%;tvmTA|9Bvn1??@{)od_tN4hRU}@U6SOt#vnS;fE><XrJ<2&uOIr#
z_M+o71(Nl9szk*V>PfQ3MlLI2Ej&xnB147mC*CTJ)hEkm3iwybJzQ0=`H<P{<NLKJ
z?z}(8qh3l?z@rY6&%wE;XR(X3Kn<Bdb#sSI)Vvm!7Tyap<%&-ir0>?RXr)8Y64-}g
z16O@w6lDeQ0l6c|s718Gm0PNPMDpmrr^_ZC<W<UE>x>ubLmF}w--W?=4DLGl*lfjf
z2P`~QubfuKJTbOE|85G1@4J)NyrSbm=^1OIqFC-q*lOX+>JiklL6ATQvad%QHEX`A
z@qNKTCU#aQq%dLv6YrGrmNu3Q6^pg|$3<|&0JPzaex?P}gcka&m0`{YyN>?C1mqL-
zk_jBzf<-Cq(v;fuz4(r(C)zHAIh!)2{0wW1w&F&lXa%Z-Dw<g!0|7;hK?O8s*sFrB
zJ4zVF&5?_FeiO!-=)F-f)_ih#eI7Bpj8QDPiJivr4r}=7pPV_H8@k7k3YRWHu2Gl4
zGVN`dp;Tp=6Tf$**DNy&6LrJ$S)~5^IMm66E-p$x(BU?Zsu5EUSv&kTLjq!^r37Gr
zwo^I&^!s6(>I#h_uO_BENd+*VZ08D4BMp9Cy&4|zW&Xln%G6(s{zM8kxGE34GD?hL
zBBkxdI-y+?XcM}I%(@O8)CTnqQxZ0MBAc%Bg3#+>S-9Lg3%Y}2wd%3dUd=P#i1@9$
z>GP<?$e-8KKYWN_`kKc{C;=G_bHFC|+&r+D8g@9r%C?dz#a|>L1X(!TnCX=MI)@$}
z_9thv^M-TIaOuX`(}Q-_Zb4~<v>}y03EMRXn=<2u1|FnS_N8@(E?QB>S+gCPhV+}1
zXakqbUQqP_q$EgXda(;__{<VTV;DwXrIMbev&)PPd>ON1|H-mbd20bQHzn^Ih$Z*t
zgOZdqzi`o2D=Ckn>_g~iHA-3-hC*zhc|Y-aQ*`!YKhlN_uvJ|0r)m!X#0b?$1BuV?
zkkBCST-{CqtZz4NDWfQ~3fg!n4$8HnATw{WlTUwBN!8eg>J)htX&V4Z_3RcUA#ZcZ
zyRRQlHF?7Vj;lqTssV{rCB(lXO4hm$FAR0*7JmYkkkT-ViV0QMlqH)>F82#Cez|`$
z5?-!x@_)n)jw02D2}*Z+AS%Ai&R902?B%%ozqYTHnUV%pj5|OfRrYUKFbF3{EU|fu
z6Vow4Y4GlJ%1;v6L*ExdRh#pLS41LN(NN|6`OIf8#L|n}oj@DN%c(XFp7k6%!~j~3
z?;Z*LB8~mHncvdt0FQZk6SW*+QGe_>VqXs2TvLP+T8`FSMtVRSS=Gyf5JHZELu`d!
z0bl4cIespex-y&_c^?IckC<$^7LyK^9XbaaM3#rbK}5|(yt*0(U+OvD@&dni$N@<B
zUv!jF<Bg*`I@Xx9v60VRGYspbqxgz5W-R-&Kv#nhx}RfgR#vEn?1iPMi}J2wvvMg(
zvGh46zWe(euOyI4R%V`)U*6=W;|qw87Bo3~I!3`f1C{c{BPFca?7hp^$p#A{Oo79i
zZ3ROUY$$x>XNp!W;?x*2L#&HRI#Un*Q@sHq6DW#F899u3f08rD5m-TYigP$15lRXY
z_rmVkR}^xtxaDMck!Hu?^@wl1b~$j98nb0a>*82vMj3j7x3;_#X<9ccCm&G<XDkK|
z4-L0>_(&7$P$hLxnj$=>!;?c|*e~~_KB^@*aesIt(#~08rCitm!!IV97vk8`eoT_U
z6fHPved<;XOa-hxSkY1vCV#)yFzH|#6FdJ+g9%R?lAirZ10U$?L)U^H`qWsXF*LuV
z9T16CmZNJ$5}2j=lnSt76X~Am7kRiU%L7uaf6s2KPgCnf$A-NX>@Xp7$fS4OZjf$v
zHA!tL^wk-BIS3tSFs`@xWng2MshlyITA<&qX&fEiB)(?!VJ=bMKgVv*x04YG^b~Zt
zEnvNna4b)sHD+)&+abD}g5t@WRIi`CUNNpMT3xLz7X;NZu|g^F;=<vPuxXtztM6cs
zJ$6acN}v;1D^Az!aUIEfGye02KqP~ytx2z6nYF-(I;eZ`Z1)PKkeVV4|FhN=R<H5)
zYV$_^Qt&;;!op&_fw>=U7Q3v5U$$f@9*+C;A7qmls$`*GSbdFP6z?QmZB2CFkfka$
z*4Ku7tvxnW9eGHDqhkyP1E%M#WGXc@Dq07L1{VF<h3MP{l!P}2yj(2!r92AO74JY_
zI|j(FF4Kl*^O;)*^LKpn^E;^UlreSRS5*2LhRGC~MLSIDP@=2r7Z#u~u2A$}tdo-K
zl2*#Z%=Rz6R33D9XD?F;^>TtD?||z=VP3;~Mo#Z3x2IF*z{+D7Z$XFCY|}EYLAuid
z2X>{XG&1!Ehw*rT0F;JiWYxWv?DF4xu)(>`=t%NLIa+4sR1D<f49a)G^AJB5a#81l
zJ#WNu0Qf^-btelcXjNzVxIES>f)+$Aw^m}Css^mUy~x5<S$xfp-lsn)qEMO|qGJ#D
z4}Pvty{hRahqi}49SsCZVzIJu8kyUE`Ir*;h05uYVpX%KIhKs&JlU0qFe)PQ<J@^@
z)wB{}@$pBk9JWsaNIE#WXleVbNwK?hDypL8E5f3n_)kNg064_X%TFyCGR4V`P&Fz#
zy`9p@YYafJ)PJnkZz12Pn11IwSZTvAdwl#7ZKI5Pz_IYc@$QR$i{!1K?Z<c5I~wTT
zKoN1F$avs}z59I)0Y;SxvxMOvs!^>WARRYcI%$1ZcTIoXMLl<HU?nVs&^N|Wj@);V
zx6?VCR{8WJy4Dikw<MjbPHmD3ZrkjbSkj9JX@%Q;g&UJGitQ`@1{um9aH+0lP}4h`
z#kwPx(k5llzN_O4>elGvuVtc$Q(P>c$`?!yZ1OCq6+;WoP|!J7iYE|$p@^1<RJN+{
zN-8b^dbmH(n|@LIhx9|Bw|9M~@f3LMQl^TF4I$hQL26<PXX!USxYn-_k@B3IJK%}I
zG(=k-F;bAS08Mcg6JVFcjc5o8A+6)Lm}Z3QLsD}pz)fSQgH5gSeP^c2UY>)!`pjc<
z0=J6}qU>e6rx#9eYH@X9K2Nk#*k@a;l-RmKxPBQip6>NM$`aA*j>m16w{LlgXY}iC
zh}b62!zo~$!ktNsZ|iJcCk{l}6;Dn{#>jteF!UUi><(OA<BjV2jB0_M|4lDDbHaq;
z<q9ybd?aactKl;12cKT)aB`-lY5}2@dXPP(+1ETQ<BAu?hutr*rWOFL%QI*7b;)5D
z<KI1w`e!R%>^hf9E8kV%M)%GPjK9x0J276xjiFTA6>XXXE@<u<pQZxw@7AdFB#)_=
zy10ld)74F)XD+=uL%xiwXpukSl8(z8|6&!FL8%h&)X*z?IpK|w*Z)G>u%Yrj>t3Yx
zH>a^?x+oA#0Wy4i#|iLG?bhW5iO{W;166h}bTd9`X_ev>!i)@(5nCf~0{DK73)Ebd
zAFvkEkL1VV<b4+$q+x=$^C(0yC@$$&*G^bg@3~wa5q4Br>DmFv6<6xZ_HOxxw*hr;
z`dy)cX+VgSksYV&+RmQOO0k@Nu}=9OqLdnu`m+$MD{W_-FR4;SGBorHz^Y5jUQxE;
zQ$(|{`yDqe5v=|Bt(^Z|va%#W?}v1~3>`*K-#6W4#lYA4D$ag9{f2ni+?_;M*eppb
zgmP3{*`uTWPU!M`X;FSw?O(@a#Ig^|gvMEB4@k`=KV7`hs0lx7(~TNbBjns-B$b5S
z$Vx1bR4<cZxdeGIY$7GghO9jQ_=?}?(&Bx|<`P<x2d`fkG^sC(_Lot~TZ6r6G4peu
zd#TB)*<$A4ftFoiRdtCYNq{&(=~ORiR{bJ6`z?e`r}v#Rgsq%fK_5GYgZTUri_glO
zB1rG)KKPz%;w&J=UX<ly3B+;qQ5ScATxaJV<!&*!k7O?bEwUGw*8yFS=RD9Xnz4p@
zLTeL7$nPya<&a;oT<2@W1P(TDg6QiTo80BZhDVag5gymowf%dC1PRI2Jl*GN8rS{-
zBikD!#wbSuyYTbENJ%m^Z*Bvby-5M8bQK!i@%4$itXvBEcs8B84A~i?MJ8Nx_QZKO
z&kxV*1KzL8r^(D)3p=(S4$y?&UtF~S-^*{*Yc{zPh>;GkZblfYN1^KZXDX`8>QEI;
zt-t8_Bbkf|3i>4tLvH;04a)Z&q4Ma46KGut^AFSa@zVw9(_QUg!&s-v%FQF#<NApw
zbLuA{l%su|IKtM;EIkClYM6ihu6{AT8Pb!QBm0$!2A&}OU2DqBYn)1Nw~+f1C;V3k
z2N6uo$)uc2=yBQT=#3Tuv3IGRk3nwz%6;hdE#k&2(?f$j4d7ZT%fd=cz==b40MJ%Y
z-P?)=*lf3cV&h%@eY?&BF&ZE;%p(Pgh$S7KDXRZjO`M;w{z`(!9slTbe@40bB#!*P
zFV~sI#F5W=26y-Sd)vV{|LxzxMcVQ|Ii|uy$|o_Ca**SGp(vGNNAspL^kVhj;c%c(
zw^x8YaR(_1U!(J>Uu(iDmYN2Sd|cIWe-)-bPGvqL<#_2E<OW_z_J*3h$J(Xukp10%
zCtP7^jTc9qF@#RIP;T0^*xB;Ch*&lW>UCIcPqjgPaiPz+|CW90%=aT!fR32pRp{{p
z=WWW))$grTb0Mbv5ioSn8U6u!(w!SR(Cnz9R$*)|j7^q#-tlXRk0hG=8)~1tWQ>CK
zL_>gp7~Fb#-cgXqP(*#|G+m_$c^g$*uV56Hxy`>GxG;sHgIeOHpQLBOl|xPQI(2H<
ze)I5Qw|i+*%M2GF!@Q3(Av|vJ(Rt==ximQcmEE_Nh2EvC{rwoxreViwWmKi)F}2kh
zN289*x|x~B(mh0H)|YrfV>+t1)6*S!!iv@@YoVo9poH%9tP?PQg?+t+t*5n~|638K
zc3jUkcf_PyWvIca>?>*VuE{+{mX6@H>OQ}5x5?unUnd1BL<il^^;d|ecLJC{%Axde
zK{vg2zwIU=U*Nv>4n&BQVjnhU5k8c0>|yv<u4X#HQQJKo4K5}^mA&=(Xjl7~2!5Z~
zOB((UeJ5Pb`R8z=+xd||zbBA}veI_W$`T>4O7hCY%<qyg{LkjPqHX`$f)y(fl70y8
zK$iL@0ebTLRKv|JnCq9KO}?f+u5zksWsu?rZn27|3uLe5h3$TcHGlYtM?`bOMRdai
z_5zR~x8K+QK#cWM@#AK$c!DM3^7Bp&b$5Cn<<;Bzgi?{7o}d@uuNeu4-0T=AGmX^}
z@(1y!5u>BcCVqz*hh00smZy1Z`P3bo&6P*d&!c0I6fPt|gOz*Y+|=Wz&MsO7Xa`g7
z-Hdr+Urh|e55`1KBK=}KY$P`)D<gV=q~@Kr!7tL+B-Bcj7XhT-R~<X8k_ySP<pt_<
z6m~xdd~WsMDM;PWEM(SejQmKC`!044Dt;clB<f3p9VTebfe@w=gYOk{>0MoXf+~3)
z;)rEDEXRQ^+1<H}<)R3w?RM@OCDTcZ%L>Y5qkad}7nH9|fb(cSV;pHnT-m>|P6K3)
z*q~bNSYZE<({S}PP^S*k6TjXYQ*wvXa&<gJ*4wPR?q;5P*O`#1RJgv?deDM<&DjxR
z^?YQ8TiYC;f-vo=XOJVpO3nOV5QI{Nv<a3f?Ymx%hVO@mHWO0Gb3lI!n~veOvdv8G
z|J*wrm{?8=T*NzWckS>x`1&Yx_K9;PTH|(2fvCi~ZjzJ)7Rk+8xs)}hlb+P&!uj?J
zJ<v1Kpn9+Od;ZP#4}sxs<m>BNDR9(;;xd?F^*kSMi0g3>YT@sPx8>um)gR#QAa4xB
zDP&f_9WEqJ90pld)efO4R|@t)9cQtySIsjTu$>zqHLZ7#-P{Q->PY$GgG!`5JjDED
z)xH%zQAuSz2*mVN#h8ZeNMXa&#oEoy#^MMw$Ih>r!237Phi}%2&7OYz9%ZjRLe#W{
zhb(}<NGjJjRsX``h-tKYPb+dYc`qdDfB!k!8Yt&mHtD$QLurW9EPr9et}{G(^{0e_
zlEN~K^Y@>Qw)cz_9ZmL};MQ$7ZGUrx(`>UumtNnXY(Bw@hS5vp4$DFRN$fI%+GXiF
z_H67B1Gzf!;+OG%64F@>(ZrmJ?Y-*8nQuRLtQV0-Sei1qgW80lnI(Z8jvsS7ge4>z
zG{!g)H{L!coz*_U1Goi~rywU@iYE6Y-DZeWsh2p+1M_Sy;2ZA9UUGU6zRLSw)S(sd
zE&e$KcppIgrDso9@XL>#$kbnA%kU!?`#28<i#y2<apKJj5u-{WPlt)CS)t6!6^&;8
z<orp)@4i?lgm7k(3j=c=bex^@EQ!>lVAm4KyKVgHO1|t@(;6cImbNcVtG^j=WvK>>
zhceo+9BfZ@l=(1!EEt`|@AQ23egfy-{&0`K(D-Z_Y({953Q;+Nc_5Ngr_u?|BU&CQ
zjp5_*>7t+(b(otoRa=FvXT8w`ej0NH4dbhqK^DROI$uydJd_zJa>=qVmW|c7OXZ&r
z6l0P|5+Hw`_bF)*0#Y^QMVsfIFh%PulTs}8z4W*KaQYGE&AXpe?dDv1*ZD)rjPWh+
z@!m|QsJ{QXzp+uK?1x!$i;NxoQ7-5d8uZ-9OQ=;Nv-hypb;De7MRfc;YiEX_7Mp$E
zGJn8zn_HEA#2u^;(iQC0>%&BAmCPQv25=S=cl4kRrseO#1cXX|=pCg`k+?+8){eYh
z*uck{s`Ros#klBtUJI3Fk!fmWGrQPMa&4!+gnTHRW^aO5L-;L1!zJ~1qVkn%S0x9y
z<5yZ|b7?1OKM-H5ivET(#(s=~i?n}e{RWk6Yzy-8@$&UB1~wdyKCBe#?Y7m@w>@>^
zXz4;9lDjTVdEdi>o_ojibML3^CVfEHp+n<;%mOZxxt{Ne4K5xgpL-Ygtoq_yzc?*v
z+p*Hr%Vk+QbFy9z2TD<IrKW>(Uw$H?_aqKU$NjWBa)PrnTXD=xb7~(pZMJ`j_dDEL
zxoiDVgh_|JDpFt(0gtU=;|EtoPtIi8!^<*$$ZsnIN~>J2FxAY>szLU4t42SG)EDes
ztt9_w&T1r<xBJ8f9aT3lHzt}2ui*@aKmSVf;hh!8RPTMXcs42zyVUzy>YWRGihN!>
z9u>bcUDbLR9(xYcOCIegxC>nx3-;RnT1gI>lb?J?{s|^Xev{coLfrSFD#L6%hKb&j
zDA+B)l9fjNK^D1aaUH*@--$vnQ&tHyzl#932^}GzT`v~781p4;$4z#PZSQPcb5AHd
zUqrUf45(|>*6zjmm8j#Ack%5c7q8SKpXtMuH)OTew)@m3#J;6*#=fm=(du2d3Gh6#
z-*5$*-(-Vxp_SXgS6L?`D$cj8U0xquB*er&SDBfoJl(`SDK38s+j^rRp_dFX^DeCv
zVw4cJe9X<98>yY((=*sIcYC;FPC$!nUWG+4eu5YWK0Pg?=jL+S`Awonvx8$fM~5Gg
zLD{$?j7)ea`U@_`^L$lM-st?9wEFDKz1pV}9VN*N%|?^t?MQOiZa$-H=DiG(OEY&Q
zXOOI$RxqR)klH{v06i=j2OF59Dm@ukZPog#Q_TB48Jm8?b2VA^9ay-OI8Qc!25x<-
zZP(tr3;?yVe`mcmfBfAgl=(an{K)mZn@hqPRD9Agp|mysEKqxf2ZVU`9dCFyQa+v?
zEg+6p&aT8;6jO2W;qULy!tJ?P7Xzl6oOi5(TnW9a6{y`xy*ev0DER}svdu!yxY6av
zfg(%|M_Z1roHBb#$vI316UlYX@G=KgP%F(?=C`@8{!!s_nXF5MQWHx@Kkk@b-+Z2F
z&D}~+K=`}I1p8TwS8H_cM8quxY@Qqrtv+8w9tXK-z-cPyjxUP_9_53EtEx&`E;}Ty
zzC1o?JeXLwta^xnZX-HoN_0jKM}FUO93KvycXiy~=;U&q-x}PT-E2V;jxQJQ0{t?V
z4YNxhX<~z$UC&oBtJlzXuZ~9+7mY@z*gPI2x|yhFA=k^7at5eDwYUmO5u^uRF%hJ0
zhl}NJpQc{aeyn<^ZU(o<IWD3^kd5ta@70Sn9_<$lRcN?gCxT6NwtQk!@C=TScZ5s=
z4vzy5ea6%|A@_s7&JH9F%g=ivZjDe64kV0c15qTn_gada3$wTSQd&Bz=X|7k=2grL
z#aF48g>U*N3ZmFoUEj1ltvl;=wp4w5URrK{N)emTOGHfcWp8b*u6B8!kH7>qgcLe7
zTGi8>%{%UX3~X&|HEf1+v<(wG=snD|x*WcI*$Lk?KA!j<=-={owW8syw{`f57q^Y_
z{rX$>eS<dGB}9~L^zh=WX@{ewy)nDj;HMeUyngy9=a7UWwTAf9H(;M8%~J{TiNfRE
z;c*9p#&SEWok~Ib)PjNhaXo_CIdNUXKaMcPGjd5Sb3k@!OE>4S@7duR+)Ra=n_(^%
zaD>QO-tAo_&&tJHSx%Z+hd6N{8WLlUAI2lcg7<fV{~#2K5mck<RF+-Pg_@RTt1g=5
z0hMO2IyPLL`DS9qj@g)VcxOdxjSb%FxJIz}W6x$m!UQ%rcpIRa&p<i&>*j#~>;Cs~
z5D_8CpufZkCI047qKy?A**+r1+NsT_hMx7_>uGko=c{0C3;9r$Sep8g91plAu1E7V
z+;j1P#A2sF*{LHlp3BYyeyd1jI(t@gFgH@PKXy^r5WE=k{CqZ)BC*r;w1mDEjLi*@
YK`xk3SJCeM=Lc0KId$0@X^XJ`1IgMhG5`Po

literal 0
HcmV?d00001

diff --git a/game/modules/tome/data/talents/cursed/predator.lua b/game/modules/tome/data/talents/cursed/predator.lua
index cf6c4ff446..992e68273c 100644
--- a/game/modules/tome/data/talents/cursed/predator.lua
+++ b/game/modules/tome/data/talents/cursed/predator.lua
@@ -275,34 +275,47 @@ newTalent{
 	getPower = function(self, t) return self:combatTalentScale(t, 5, 15) end, --damage reduction handled in damage-types.lua
 	getCount = function(self, t) return math.floor(1 + self:getTalentLevel(t) / 2) end, --vision handled in player.lua
 	doMarkPrey = function(self, t)
-		self.marked_prey_tbl = {}
-		for __, e in pairs(game.level.entities) do
-			if e.marked_prey then
-				self.marked_prey_tbl[#self.marked_prey_tbl+1] = e
-			end
+		local ok = false
+		for _, e in pairs(game.level.entities) do
+			if e.marked_prey then ok = true break end
+		end
+		if ok then self:setEffect(self.EFF_PREDATOR, 1, {power=t.getPower(self, t)})
+		else self:removeEffect(self.EFF_PREDATOR, true, true) end
+	end,
+	on_learn = function(self, t)
+		if self:getTalentLevelRaw(t) == 1 then
+			t.callbackOnChangeLevel(self, t)
+		end
+		t.doMarkPrey(self, t)
+	end,
+	on_unlearn = function(self, t)
+		if self:getTalentLevelRaw(t) == 0 then
+			self:removeEffect(self.EFF_PREDATOR, true, true)
+		else
+			t.doMarkPrey(self, t)
 		end
-		self:setEffect(self.EFF_PREDATOR, 1, {power=t.getPower(self, t), count=t.getCount(self, t)})
 	end,
 	callbackOnChangeLevel = function(self, t)
 		self.mark_prey2 = self.mark_prey2 or {}
 		if self.mark_prey2[game.level.id] then t.doMarkPrey(self, t) return end
 
 		local marks = {}
-		for __, e in pairs(game.level.entities) do
-			if e.rank and e.subtype and e.rank >= 3.2 and self:reactionToward(e) < 0 then
-				marks[#marks+1] = {e=e, rank=e.rank, subtype=e.subtype}
+		for _, e in pairs(game.level.entities) do
+			if e.rank and e.subtype and e.rank and self:reactionToward(e) < 0 then
+				marks[#marks+1] = {e=e, rank=e.rank or 0, max_life=e.max_life or 1, subtype=tostring(e.subtype)}
 			end
 		end
+		table.sort(marks, function(a, b)
+			if a.rank == b.rank then return a.max_life < b.max_life
+			else return a.rank < b.rank end
+		end)
 
-		if #marks > 0 then table.sort(marks, "rank") else return end
 		self.mark_prey2[game.level.id] = {}
-		for i = 1, t.getCount(self, t) do
-			if #marks > 0 then
-				marks[#marks].e.marked_prey = true
-				self.mark_prey2[game.level.id][i] = marks[#marks].subtype
-				table.remove(marks)
-			else break
-			end
+		local nb = t.getCount(self, t)
+		while #marks > 0 and nb > 0 do
+			local m = table.remove(marks); nb = nb - 1
+			self.mark_prey2[game.level.id][m.subtype] = true
+			m.e.marked_prey = true
 		end
 
 		t.doMarkPrey(self, t)
diff --git a/game/modules/tome/data/timed_effects/other.lua b/game/modules/tome/data/timed_effects/other.lua
index b5bf3908db..14cbd32648 100644
--- a/game/modules/tome/data/timed_effects/other.lua
+++ b/game/modules/tome/data/timed_effects/other.lua
@@ -1917,27 +1917,25 @@ newEffect{
 	decrease = 0,
 	cancel_on_level_change = true,
 	long_desc = function(self, eff)
-		local desc = ("Hunting:")
-		local desc2 = ("\n%d%% Received damage reduction against SubType:"):format(eff.power)
-		if not game.level then return desc..desc2
-		else for i = 1, eff.count do
-			local e = table.get(self, "marked_prey_tbl", i)
-			local etype = table.get(self, "mark_prey2", game.level.id, i)
-			if e and e.name and not e.dead then
-				local mprank, mpcolour = e:TextRank()
-				desc = desc..("\n%s%s.#LAST#"):format(mpcolour, e.name:capitalize())
-			end
-			if etype then
-				for j = 1, i do
-					local etype2 = table.get(self, "mark_prey2", game.level.id, j)
-					if etype2 and j ~= i and etype == etype2 then eff.unique_subtype = nil break
-					else eff.unique_subtype = true end
-				end
-				if eff.unique_subtype then
-					desc2 = desc2..("\n#ffa0ff#%s.#LAST#"):format(etype:capitalize())
-				end
-			end
+		local desc = "Hunting:"
+		local desc2 = ("\n%d%% Received damage reduction against:"):format(eff.power)
+		if not game.level then return desc..desc2 end
+
+		local preys = {}
+		for uid, e in pairs(game.level.entities) do if e.marked_prey then
+			preys[#preys+1] = e
 		end end
+		table.sort(preys, "rank")
+		for _, p in ripairs(preys) do
+			local mprank, mpcolour = p:TextRank()
+			desc = desc..("\n- %s%s#LAST#"):format(mpcolour, p.name:capitalize())
+		end
+
+		local subtypes_list = table.get(self, "mark_prey2", game.level.id)
+		for st, _ in pairs(subtypes_list) do
+			desc2 = desc2..("\n- #ffa0ff#%s#LAST#"):format(tostring(st):capitalize())
+		end
+
 		return desc..desc2
 	end,
 	type = "other",
-- 
GitLab