From ee1357a8483134f661b0cbb841fe9a2d8b268de3 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Tue, 7 Feb 2012 21:06:52 -0200 Subject: [PATCH] add combat controls --- TODO | 1 + modules/client_topmenu/topmenu.otui | 1 + modules/core_lib/const.lua | 8 ++ modules/core_lib/globals.lua | 5 + modules/core_lib/util.lua | 13 ++ modules/core_widgets/core_widgets.otmod | 2 + modules/core_widgets/radiogroup.lua | 43 +++++++ modules/core_widgets/tooltip.lua | 2 + modules/core_widgets/uicheckbox.lua | 8 +- .../game_combatcontrols/combatcontrols.lua | 121 +++++++++++++++++- .../game_combatcontrols/combatcontrols.otui | 43 +++++++ .../game_combatcontrols/icons/chasemode.png | Bin 0 -> 1962 bytes .../icons/fightbalanced.png | Bin 0 -> 2162 bytes .../icons/fightdefensive.png | Bin 0 -> 1726 bytes .../icons/fightoffensive.png | Bin 0 -> 2119 bytes .../game_combatcontrols/icons/safefight.png | Bin 0 -> 1910 bytes modules/game_inventory/inventory.otui | 1 - src/otclient/const.h | 2 +- src/otclient/core/game.cpp | 33 +++++ src/otclient/core/game.h | 12 ++ src/otclient/luafunctions.cpp | 6 + 21 files changed, 293 insertions(+), 8 deletions(-) create mode 100644 modules/core_widgets/radiogroup.lua create mode 100644 modules/game_combatcontrols/icons/chasemode.png create mode 100644 modules/game_combatcontrols/icons/fightbalanced.png create mode 100644 modules/game_combatcontrols/icons/fightdefensive.png create mode 100644 modules/game_combatcontrols/icons/fightoffensive.png create mode 100644 modules/game_combatcontrols/icons/safefight.png diff --git a/TODO b/TODO index efdad0b1..e4c9a02c 100644 --- a/TODO +++ b/TODO @@ -61,6 +61,7 @@ change Align/Anchors lua API from enum to text == Client make possible to reload modules +fix modules recursivity, it makes client crash implement left panel with dragging windows clean sprites cache periodically create a shader manager diff --git a/modules/client_topmenu/topmenu.otui b/modules/client_topmenu/topmenu.otui index 540bd9a8..288704b2 100644 --- a/modules/client_topmenu/topmenu.otui +++ b/modules/client_topmenu/topmenu.otui @@ -61,6 +61,7 @@ TopPanel type: horizontalBox spacing: 4 padding: 6 4 + visible: false Panel id: rightButtonsPanel diff --git a/modules/core_lib/const.lua b/modules/core_lib/const.lua index dc65c712..de7a2fd4 100644 --- a/modules/core_lib/const.lua +++ b/modules/core_lib/const.lua @@ -309,3 +309,11 @@ SpeakChannelRed = 11 SpeakChannelOrange = 12 SpeakMonsterSay = 13 SpeakMonsterYell = 14 + + +FightOffensive = 1 +FightBalanced = 2 +FightDefensive = 3 + +DontChase = 0 +ChaseOpponent = 1 diff --git a/modules/core_lib/globals.lua b/modules/core_lib/globals.lua index f74bf79c..5ef31a99 100644 --- a/modules/core_lib/globals.lua +++ b/modules/core_lib/globals.lua @@ -51,6 +51,11 @@ function displayUI(arg1, options) return widget end +function loadUI(otui, parent) + local otuiFilePath = resolvepath(otui, 2) + return g_ui.loadUI(otuiFilePath, parent) +end + function createWidget(style, parent) local className = g_ui.getStyleClass(style) if className == "" then diff --git a/modules/core_lib/util.lua b/modules/core_lib/util.lua index d0bc1292..5a83a349 100644 --- a/modules/core_lib/util.lua +++ b/modules/core_lib/util.lua @@ -57,6 +57,19 @@ function disconnect(object, signalsAndSlots) end end +function newclass() + local class = {} + function class.internalCreate() + local instance = {} + for k,v in pairs(class) do + instance[k] = v + end + return instance + end + class.create = class.internalCreate + return class +end + function extends(base) local derived = {} function derived.internalCreate() diff --git a/modules/core_widgets/core_widgets.otmod b/modules/core_widgets/core_widgets.otmod index 95836e90..0145bb15 100644 --- a/modules/core_widgets/core_widgets.otmod +++ b/modules/core_widgets/core_widgets.otmod @@ -25,6 +25,8 @@ Module dofile 'uimessagebox' dofile 'tooltip' + dofile 'radiogroup' + ToolTip.init() onUnload: | diff --git a/modules/core_widgets/radiogroup.lua b/modules/core_widgets/radiogroup.lua new file mode 100644 index 00000000..d4c0c833 --- /dev/null +++ b/modules/core_widgets/radiogroup.lua @@ -0,0 +1,43 @@ +RadioGroup = newclass() + +function RadioGroup.create() + local radiogroup = RadioGroup.internalCreate() + radiogroup.widgets = {} + return radiogroup +end + +function RadioGroup:destroy() + while #self.widgets ~= 0 do + self:removeWidget(self.widgets[1]) + end +end + +function RadioGroup:addWidget(widget) + table.insert(self.widgets, widget) + widget.onMousePress = function(widget) self:selectWidget(widget) end +end + +function RadioGroup:removeWidget(widget) + if self.selectedWidget == widget then + self:selectWidget(nil) + end + widget.onMousePress = nil + table.removevalue(self.widgets, widget) +end + +function RadioGroup:selectWidget(selectedWidget) + if selectedWidget == self.selectedWidget then return end + + local previousSelectedWidget = self.selectedWidget + self.selectedWidget = selectedWidget + + if previousSelectedWidget then + previousSelectedWidget:setChecked(false) + end + + if selectedWidget then + selectedWidget:setChecked(true) + end + + signalcall(self.onSelectionChange, self, selectedWidget, previousSelectedWidget) +end diff --git a/modules/core_widgets/tooltip.lua b/modules/core_widgets/tooltip.lua index be0a5929..6f8177c0 100644 --- a/modules/core_widgets/tooltip.lua +++ b/modules/core_widgets/tooltip.lua @@ -57,6 +57,8 @@ function ToolTip.terminate() currentHoveredWidget = nil toolTipLabel:destroy() toolTipLabel = nil + + ToolTip = nil end function ToolTip.display(text) diff --git a/modules/core_widgets/uicheckbox.lua b/modules/core_widgets/uicheckbox.lua index 09685d2d..016551f5 100644 --- a/modules/core_widgets/uicheckbox.lua +++ b/modules/core_widgets/uicheckbox.lua @@ -7,9 +7,7 @@ function UICheckBox.create() return checkbox end -function UICheckBox:onMouseRelease(mousePos, mouseButton) - if self:isPressed() and self:containsPoint(mousePos) then - self:setChecked(not self:isChecked()) - return true - end +function UICheckBox:onMousePress(mousePos, mouseButton) + self:setChecked(not self:isChecked()) + return true end diff --git a/modules/game_combatcontrols/combatcontrols.lua b/modules/game_combatcontrols/combatcontrols.lua index 4494fe70..521d6501 100644 --- a/modules/game_combatcontrols/combatcontrols.lua +++ b/modules/game_combatcontrols/combatcontrols.lua @@ -1,13 +1,132 @@ CombatControls = {} +-- private variables local combatControlsButton +local combatControlsWindow +local fightOffensiveBox +local fightBalancedBox +local fightDefensiveBox +local chaseModeButton +local safeFightButton +local fightModeRadioGroup +-- private functions +local function onFightModeChange(self, selectedFightButton) + if selectedFightButton == nil then return end + local buttonId = selectedFightButton:getId() + local fightMode + if buttonId == 'fightOffensiveBox' then + fightMode = FightOffensive + elseif buttonId == 'fightBalancedBox' then + fightMode = FightBalanced + else + fightMode = FightDefensive + end + if Game.getFightMode ~= fightMode then + Game.setFightMode(fightMode) + end +end + +local function onChaseModeChange(self, checked) + local chaseMode + if checked then + chaseMode = ChaseOpponent + else + chaseMode = DontChase + end + if Game.getChaseMode() ~= chaseMode then + Game.setChaseMode(chaseMode) + end +end + +local function onSafeFightChange(self, checked) + local safeFight = not checked + if Game.isSafeFight() ~= safeFight then + Game.setSafeFight(not checked) + end +end + +-- public functions function CombatControls.init() combatControlsButton = TopMenu.addGameButton('combatControlsButton', 'Combat Controls', 'combatcontrols.png', CombatControls.toggle) -end + combatControlsButton:setOn(true) + combatControlsWindow = loadUI('combatcontrols.otui') + fightOffensiveBox = combatControlsWindow:getChildById('fightOffensiveBox') + fightBalancedBox = combatControlsWindow:getChildById('fightBalancedBox') + fightDefensiveBox = combatControlsWindow:getChildById('fightDefensiveBox') + chaseModeButton = combatControlsWindow:getChildById('chaseModeBox') + safeFightButton = combatControlsWindow:getChildById('safeFightBox') + + fightModeRadioGroup = RadioGroup.create() + fightModeRadioGroup:addWidget(fightOffensiveBox) + fightModeRadioGroup:addWidget(fightBalancedBox) + fightModeRadioGroup:addWidget(fightDefensiveBox) + + connect(fightModeRadioGroup, { onSelectionChange = onFightModeChange }) + connect(chaseModeButton, { onCheckChange = onChaseModeChange }) + connect(safeFightButton, { onCheckChange = onSafeFightChange }) + connect(Game, { onLogin = CombatControls.online }) + connect(Game, { onLogout = CombatControls.offline }) + + if Game.isOnline() then + CombatControls.online() + end +end function CombatControls.terminate() + if Game.isOnline() then + CombatControls.offline() + end + + fightModeRadioGroup:destroy() + fightModeRadioGroup = nil + + fightOffensiveBox = nil + fightBalancedBox = nil + fightDefensiveBox = nil + chaseModeButton = nil + safeFightButton = nil + combatControlsButton:destroy() combatControlsButton = nil + + combatControlsWindow:destroy() + combatControlsWindow = nil + + disconnect(Game, { onLogin = CombatControls.online }) + disconnect(Game, { onLogout = CombatControls.offline }) + + CombatControls = nil end + +function CombatControls.online() + Game.gameRightPanel:addChild(combatControlsWindow) + combatControlsWindow:setVisible(combatControlsButton:isOn()) + + local fightMode = Game.getFightMode() + if fightMode == FightOffensive then + fightModeRadioGroup:selectWidget(fightOffensiveBox) + elseif fightMode == FightBalanced then + fightModeRadioGroup:selectWidget(fightBalancedBox) + else + fightModeRadioGroup:selectWidget(fightDefensiveBox) + end + + local chaseMode = Game.getChaseMode() + chaseModeButton:setChecked(chaseMode == ChaseOpponent) + + local safeFight = Game.isSafeFight() + safeFightButton:setChecked(not safeFight) +end + +function CombatControls.offline() + Game.gameRightPanel:removeChild(combatControlsWindow) +end + +function CombatControls.toggle() + local visible = not combatControlsWindow:isExplicitlyVisible() + combatControlsWindow:setVisible(visible) + combatControlsButton:setOn(visible) +end + diff --git a/modules/game_combatcontrols/combatcontrols.otui b/modules/game_combatcontrols/combatcontrols.otui index e69de29b..e9a3af05 100644 --- a/modules/game_combatcontrols/combatcontrols.otui +++ b/modules/game_combatcontrols/combatcontrols.otui @@ -0,0 +1,43 @@ +CombatBox < UICheckBox + size: 20 20 + image-clip: 0 0 20 20 + anchors.top: parent.top + margin-left: 5 + margin-right: 5 + + $checked: + image-clip: 0 20 20 20 + +FightOffensiveBox < CombatBox + image-source: /game_combatcontrols/icons/fightoffensive.png +FightBalancedBox < CombatBox + image-source: /game_combatcontrols/icons/fightbalanced.png +FightDefensiveBox < CombatBox + image-source: /game_combatcontrols/icons/fightdefensive.png +ChaseModeBox < CombatBox + image-source: /game_combatcontrols/icons/chasemode.png +SafeFightBox < CombatBox + image-source: /game_combatcontrols/icons/safefight.png + +UIWindow + width: 130 + height: 30 + margin-top: 10 + margin-left: 6 + margin-right: 6 + + FightOffensiveBox + id: fightOffensiveBox + anchors.right: next.left + FightBalancedBox + id: fightBalancedBox + anchors.right: next.left + FightDefensiveBox + id: fightDefensiveBox + anchors.horizontalCenter: parent.horizontalCenter + ChaseModeBox + id: chaseModeBox + anchors.left: prev.right + SafeFightBox + id: safeFightBox + anchors.left: prev.right diff --git a/modules/game_combatcontrols/icons/chasemode.png b/modules/game_combatcontrols/icons/chasemode.png new file mode 100644 index 0000000000000000000000000000000000000000..f3ef70586505c758d93ff0a181e9a8bcd553b872 GIT binary patch literal 1962 zcmV;b2UYlqP)mA2M-<~~aXgoYUAX?*`19HTR#e!?s zuJOVPFL3z8Apju+Hk%Dv3&t3nvnZvAF=E!M6(Ix?FquqPtyUC8Nr;iAshLd1Jonsl zJo)640NlTSe~8Y~_dS!z1Q7v1YmEU#N(n6*YaOO2@ZOVRr0;vmvgG#d+nk)7@ZpCa z0t#y_bzQUBZ0NcUV+>_kQdSkBwcwn^2Txg+q!=;Akbt5nI5;@q@Gz%(r?rAu7Ac#)4j`e=8v)oR7j(GfSFy~*C*jIQgjwkL!@(~JO+ zs;Y@Gk%%az5K(yVIXpaMyWR5Md+%Wf;r4ycty{O4&*$v#U!@t1FvhU$IyRe@rfD#c zFh&zXL~Eh%Ek$AId&_IDy#_;b0H)I^i^YOB-gtxK<72${%=Y#GXxkQRE#iI1f-KB1 zR)((cdH3Dh+`0292L}fzr2r_)lIe8H+i$*x~Z|&vRp0! zaL%!}w}%Xqv%kL&z{$x8N-3^h-A4w^#u%xpiq&$t`z%T+nr6gkG(tq7wWeLKDT{)p zX_(LFc<;G;_rCx<{`h4?D@3w+IOnM9nyM;u57w)7ZiMqxRYi;uP=pY;a^(uM*^KRW z%iX)5VXb98zd&8pC_*n&oXaVfWr6da7z68d%V;!0YaxWdxpU_!%aX-n!TtO9 zY1@|RbV60tq(MqbDaPY5-uo;Yr4*tRMN#Y|10Y&+`SK+IzWnk_w%aZ1c1_bXJT`xf za_~g0HP%|nG8>9fBFONHG2xs?Yayk?`|rQcg9pbPA3vboY+hV@_x(_cIK0=0 zsGXyqF-Al%gXm4x))llih-6_mO+(*XjM0NxBzkKhC5$nI5Oz&CgICve+`M@cF{VIk z!39SM0TE5xwm>3;fO9TKp!H73XDJ%3NeR67h?snCyJ?xtW{jKB5Ka8nh2DEkPfv#i z2z6cWzTa-Qh^PTneHOMB;nAZ_I$Mk(qBGLS!VeK}>ObVfzRJ?>H8s+s(8LW&7r`aF(x4Jcwt8B*F9ybpNq2T(y_4C^1RnNFwN zJHAIr$9cX|Hrs3t+hMH`rH6VHXl+QZBtEh9wEQuA~2Dj~XlX{*}40WJ!D}vYM`ti-No4 znATIAb8NR;Kw;MFHRsQtA3&8*0@gZ;!f?)?C;l{Yo$CNRY#%cJcn)b;nEDN&jyq8G zeV1k9oF}D(DGf1(463ffdq@4N8jEGkI!ovKo1Ht4$78ezCnqNqWl3GvNYgZo#v}T^ zXFY&wbFjhw+Oqk}hRgHIe6aX{kN^2G4GoLGE!d1Uh-BTJZ5*rR67N06dyf*KX~y{I zAx8FoyGQwKNhIZZx|Wr~93;*`l`Oz1tM zQA6>kg5&BKXB=fJx$yOc9QhX;cmh&LDAadA6+*!DUB_%T!-qf!p7naeWHMsB8t1y2 z0vNjQGw@ZZ2qAq7RA(ESoIyzqD~HzK0F^Nqqd}>BV-12(Q6U0lQ4E$RIOnp#iU?v1 zLJr@1k8>VlvKzN;JB*^D_=CdkpK{^hWAw`5yvG=mn_&#A)e7_c^Uv=hGQ$R|hQABe w+8x<|%#}5Sry?On%Ccm;?I{XPHt)#)0PZ6s$iipyvH$=807*qoM6N<$g2fcUf&c&j literal 0 HcmV?d00001 diff --git a/modules/game_combatcontrols/icons/fightbalanced.png b/modules/game_combatcontrols/icons/fightbalanced.png new file mode 100644 index 0000000000000000000000000000000000000000..311353876c25a89572efae50fa6c8ad880b2742c GIT binary patch literal 2162 zcmV-&2#xoNP)P5J-;2meV# zK~zY`U6)&kUDX-Kf9tX@=bU}UximAA*qJ0ogd`}Y4b}0bUSf=;+BTw!KrhWqZlm#tg3 zqP1phYz%<1D)G*vq@=D5QZ^M)RTZ)-_KcGTx4Zsg~`cD78VwmnVH$t zH26T8rj%t#T~|2gXtmk^$RtVeJ`nJ%tgK+I#W~CR`Z_00oFLD0vMl3{JMLtBVw^nx zf10g!yV18S84d@uS}i05v{sZwMXS}O+Z{s)iBg(Nmo9PS$Ps$I9%Ex&_T9dZBuVJ^ z`z$YC!CFhV+a*mB>bj<`YoxUf?>)7tId$q3Ter?KHrB;jgHoE6l@;E6^G#M)SDBcY zV0wC*+1XjLEMwp8w=*|4N0O#wS=LB)_dWN#uyp=BMN!aO?~!F4_UzqDRaFcI0|2rt zqucEgMG@U@mz_IzB81@J!GkEJIC=6U&Ut#h9$E-NtJNlQ7HbWQi;G-YUgqXqyO^Au z1fbjP^6w*WQ5FS{KmK(lCMGy^=n&VgUE}rFUnh!V!7-I+_pyN2gSc~_LJRgu{ z9m=xggAYDnW1Km21^}%!x7~Id{eGY0Z@!4nmzR0#=utksZ~;@-95`?Qtu@DwAIEu*7E&TdpZ5V{EJ{g22qP>> zq>uyxS}FeduYW-ZSm$`>op%T!Y|^Hcw$OS+VE`!waU3%k4Cr(^#BsuKIKX>{F_sWV zc;`rxgb)JGIZm87fs~T6EOE}Fj~zS4+WI-7ZB@;k_k_BGUE*Ze&y&lXg07zJSWd{j4{MVKBt20Zle~Iz29^OM;c_Ix_B3WG<mr1}7(>?0kRb%Z=z1Z9pf-Wv z0&(uG)t@{pMEyvCoeh( zr$OArBahB-@Bmz0hBy)s*fc6*>QQYfWE4fDX^L|Jk7Lj`)OJ8s2TpwifBo|S!c`Dk zdF0V)_J0{xS3Pmuq?xu_Xss#B5)jC$s+#)IlB%ewiYx5<(hwyfPT=qVfIt5J5`>E& zwsH6U6Lc~`o)5To?JCweI-L$ll2BD85@<*g0>&C%{#DMx9fDhKf?^0s3`ZB?m%q3M z;Vg*lbjPNcp8f)zPKU29SZ=v_jW~`;(-gI3%a#`=r=}>2g0d{Ra=W+6lY&R45gYYLdquT|=wuJoC&rb6<@3%WDI+Y}ta?xpQZj-@YAdEY3R^UFUAu zRq^d_t?|hx0f4=?3SRw9i{2pchu@_Lu^q6~)fxvMjHr!a@18wKr8WItzqt|{OB~09 z5cu$P#BcvJ!2=IU?t4J;%C9H*=*%>qeKy6jPuD;WSbqM~>*Rw0rmk_$p-o+rBr(o6 z;2aEwbUJOyvgEz@BcA_JW2GN{lmZs5HBUX&B7|$a`m*JT?-}wO4j<_>CbfZoF>v?xj6n!V9LGQd(+#j%@6l3n|2>8zQJg-v8@+q?ZnkaP)@(P58l;bIsT*+J@R*I) of%hKg98nZemNlPV7L3;5e?~)K`DvRGp#T5?07*qoM6N<$f_5P3ApigX literal 0 HcmV?d00001 diff --git a/modules/game_combatcontrols/icons/fightdefensive.png b/modules/game_combatcontrols/icons/fightdefensive.png new file mode 100644 index 0000000000000000000000000000000000000000..3829a215ddda8b5c02c7bfd4b25a0d4d70d8d6c8 GIT binary patch literal 1726 zcmV;v20{6WP)TD+LHK2DH|Q2qJ>D z#lc{BaHO>+ga~AEh7de&-n>E0c6O+%8m%=sCzMiz-eZiB)oMk~84-nZZhYUiElNpm z*drq3oH48Al9Un|sOy^TcFXSW9#vgo`_Q_sLurlCnv{yu^?J>Ey{4{flu~0#3 zq6i@}-`(YRpMQ=qh8QDS>k*ai4VGv!_wV1QX&SWF7-KNjVze$HDy?zWQCAgLuU_TR zqeraQ>#+#i?G~jJ)>`)V_PBlfHhX*fwC#_0@9DaZ6eDJ=8nD@{nM@|7f_FK zJt-wpN&s|Si!lZeyzffEwARF!h%w@vLqq_^KTReRL=DjBbk1+=4s#2J$s!1u6Nd<`#ptQj7NBR_q z656&Mqj1ilwWe)b+P1+thk=aNij*>Z-xn!|eV5}XBsp?6M_nysqJsx`U<(C{E zA9HYUFjja#clq)m$H&J!eE5*fW`lE%&3cXZWjvLLP*pWmU89tsl;Z2JzT)ZAr`))4 zgTuqaF_(vjhupmRYrc8<4bPrE>&GtOstRijB7#{hSA}Upq^>L4w#ECv ziP)pkJqQsg?bdaq6p_1k@8;7Vejs@N!GWO&rNIkj4H7W?e(@T3Qm$RQmWPLruZu=P z2#6@ORwFs63n;B~?9S&HfXkP!V2nWoy!X^~P1gmCQ9a5;7XtKDH&9;68FI;O+qT@g zbql4n!5EDXz89fFrjSOe(pqDBVH(h-lrUP8^T6hP)!VLRKA$tGr+w?h4}>a&z`J+v zMxm;zYJ6WDms_st8vqVJ;R6mdhp6 z>GZv3mv+&kPnoHIEkthHodwOTTpP2VG0 z0bPG9;0#y;hp->^QESD@u11zOB7)MI;3Jt-k}gH7Y5Pzw_eLDB51axm2!a-k_W`AZ zX4@1#Y_?mp7PQi3?0SJ>(i=PnLXYwd@N*y*gTC{4-}SwzQPx`Ox+caz`!wnYCn9injUB_y0^Fwj_7_;KR#a8RYPlqYfEiS+t|!D4A!kwo{wf?@Ib!jf1&iqd z{@ok9346cTWB!jh@^?ixW!|g0?3hX$!*a1i1cDDZ=g2wZJ5T;&rn*<5v??K90c92T z_ZIn+jPqO0cZI!u*HKk&6sq-l!)!JkHv#)k$ALfKr$7G$z`?x(+a=j!*7=QudiAt{f)gtR3mid(Y0!&ihG`o}ohsWynq0Qn%Y}*{`2e z?}aKCq4I-3g_5e(YK6Ie{W?cSM+L66h4(J3YlE^48Z&54j1g-sP19kFqL6py{~6WS U3D?B#DgXcg07*qoM6N<$f*1HY_W%F@ literal 0 HcmV?d00001 diff --git a/modules/game_combatcontrols/icons/fightoffensive.png b/modules/game_combatcontrols/icons/fightoffensive.png new file mode 100644 index 0000000000000000000000000000000000000000..2fb6e794cc19769ffe5d44409755f709f76842df GIT binary patch literal 2119 zcmV-N2)Or&P)SK zK~zY`U6)IYRrMXmKmW&h-Ft^&piNB^leT-?u8du{ z>8iVKn>00j8L$mbN(vdRi&6~<(mmx_J9qBfbI$+S#kn)4{*$vfkNp3? z$M^9&;>8z#9Ho>90nT~yJi{1^QWB*UF-EL&5F<({LI@;DLI{BfNGY+#0C4Z#J+zd9 z_inz2RtgX}XVF?Cgg^*EmStFL2_fLTLrH~{k|aqm#sZNT!CJ%e@-njB>CkSq$ESOw zQdnz&CgOg-PY3}i6?v8e;Js%w8ljX#YmK!AAp{`=^l*J0?>!OdbUH{Wky6oL>r)gt zS(Z|kB~mG}G(`wOk|gALPK*)nJyJ>llu~FA#28Uhk>>^HzjGdEEf+3aU@#bvrYY@q zo6%^55CRZ%IvviPJBJX0*Is)Ktu<+yl4coFDT%cP=N(Cs;GJV`ZjN*3&$DaSuC4T~ zwUlMa&Ye3rd-g1Q_wEInI$LWQtgqvpL!CHr;+2(^RS?kc^|*7V%bq>c%+1a5_1Re- zeDMYSUJtD`)6>&in{~TgF24RcbyXpRBm_@YRj8+*e)^UB_wN&8AWKs=Ha56>cZr#q z8D?f@*|%>WpMU;2J9h5m{Q2|j-o2ZpyGvZWaFMmOHA09;De&IY>-Er8RUxGyMnPTI zBuUEZYLA751zb4iUJK0trgw}w3Zw^ z_!wF%-hclCLI{Kq*j#bU7Nrz3GkefU!eX}zg8>^G8yI8I&iMwAiN;ySV~-u=z<~pF zIvq}&IKkA^6e}w$2qAdrp@%qg<_y=bU+0-;p5dd9KH{G@Z_;YF5kj!Kx{Az;9AgZF z!GI6~^Yim;Y;5rCv(GX$HAS!2V}5>~OPAiD*XuDgHN~k@rx*+dT)upnBuQ8w3^1ml zrxZd^6fIh<7E%hzvgGgAt`S1O7{k@8S6N6V zAp~-`K5QCc9eGi3{P=N>A3Mg?t5+EghdlY@lUU~{@{A)#jxZPuSXfx#*s)_AJ$e*` zz#4qjE z#mSQ=0l0PhHtT}{09puv924F-$D41y$&DK~kVMFX| zW7qcWT~@)$ znc?bi$Xs3Hy(h~uzE;=#bvUFmJIhMH&vykFV@T7C7-JKmR0`)BtYulo+WI< zDPCP%MC{$mukPM$(7tC6@!mb2cb=-Q|IetjR>;kBq2>R@}fX%O;uHZK-YEM;73bB5C{!NjG+Mjk)(tM7hm!*1QI|9!GYc? ziIn_%`*r~8x@xFrts_Y^N-Mnc{HWdL3E;O69`OBkyNT@Mk3lJzo8#5RMSedV^8CXO z^RF2BVZTq&YLVwTV*mdAaeB`lHiko-bEIiTQRFOmPdYgXS`!x+`9W3Tf#2jgV((sX z4%6##D$6j&P*oL&43> zyxeL*S#qV_20+Zt&c>OUnXQrbo8Ge>m{$sfXnZ6D5}kkm=Pbl8$C7W=HBJcL)|#iD zdTQ)?N+HIx%iGO4XwgizWmzJGL^NMCszO8n#yJ+oZkbBSa5zLCJa~}l>FLH(lcZ6U xG0rx{b<<-u{|-V3c<)J)gsL)VEs5i({|5tKO)64P%Ao)N002ovPDHLkV1gam)%5@X literal 0 HcmV?d00001 diff --git a/modules/game_combatcontrols/icons/safefight.png b/modules/game_combatcontrols/icons/safefight.png new file mode 100644 index 0000000000000000000000000000000000000000..2117067a70122f5354dda65200b68524859937b8 GIT binary patch literal 1910 zcmV-+2Z{KJP)*7|`G`>~Ut9s|2^FROd z|DUIxfBpwqDTPvylHk1~#)#G$tu;AkQc3`5tq~Edwd9=1fKrMSBLI`h1gjK$_|bbj_R!V=M`X(D#9yGXPap zVVy&llp{$J))wq$^EuX9wzs!=?z!(%*EP;Lu3h^T!{Lw^3(i&L*8%7AIg%23)itFQ zi^T$KEs_$0!2p2qc+AGe27|$X*=)veIHV5&r8HWX1f270R%l}kDMla^c3$s*4Sl36e$T>7c4^v*uL-4df6f8==+{$p7}0q+j4Yt#G{Ws zN?q4jYuVl1#rq1$Lff`fRZUe@K*swD0PCDbB%?H>l(5!PRTUuwE?>S}__m}@jFF?G z36G3M1QF)5*_vV@1ibfX$QYv`t2GWsM@OakDE9XD*xTLZ`1qLle9nt6zQ`-DzRJb% zMMMN+3;-gzOxOxPV+x@&aO>7BM1+HbeZ2QL=h)fVK|~mhMocCX_V@RefrO@MaITD_ z^_3@tKuQT;Rm8=DgM$O6((06p>8M8LgBm z;MO%}$;p$`Q|{ckvm80ad_Kdua`5%**Eu{qL_|fowr44VnREIbB>(h z?YG}v^U(W>>GYHvH*Rp_=1o@Py0NiQ#6)XC2rKFtk_aLR5mShrGq-Qwrt5k}qlfX{ zb9#EpWHO=aI=Zf3s!*925m_seRZ5|t1d@c-3Zo4vM)vpjI6S;l6eT5;0%sjn<%_y3 z1)((6AS(=4ba`-PobzkyXsxlv;Mezxuv%m2x{eql8Su_yS1GUlbY2gus;27}Cn|%B zoG;&6gGfb-AiwZ~M^WykFxJW5jBWjsb(h zW})d82#}4X*M_7u@&AIRv?R7xibcC9t_RfK({~*%!`A(Kn6vw!6d`9iG(l_9Ll@A4 z0SSfj4|te!E*P%3XOu?zo<Bf{|k^&?|;-+F`KKF4HcxVG~t&2Wo; zxd>zmwFiSA0NESFD^YscXl7W z8iJf@HX3x!nY=VAF9|n0;Zh|?ywCJ-m)R%pGdnrsx4-`rd3c%s+gOZ+POhv|H_|5eDUD(Sc}3y5|Y z=Lkzr0aa`?=ZrQ6iJ+C{_Hm1|mPZ=HC@b#vkxPx?r{DMjjZW;p^9~CPQCn12G)+@D zyc_~zELvx^fvV!Oz$;(*5}TWu!~GL}w{yq~mpo5=@$;O#`w?txuxW(8&otJpJ;i&E zcFs{ZbrDPJuyw;>-?Q_C!&8@P++;nBDV#d2)5)>v%}^Vu9@ zG?Ft5V;DYmiMI|8*uAyG6>D+8r7&kl-~%%I%Hkh-h%WRPYuBD4BG?$h+N4Dic+cEg z@@UK_eaBvm=nTY!D2@0Ex3xt&r|_#;2C%D=S4u4+C}S`ioAg>EN@H{p*s8A36rou8 zOxJZwC4i=B3bB=bu!yH5gb;vC)ij8LYz(3eAw#!(Ls)srYNHK(PusTG#~**3@puXD w@^wKi%ZcY6Ua9o?O02c?eOcafhMY7117puc&`XV-P5=M^07*qoM6N<$f;WGf*Z=?k literal 0 HcmV?d00001 diff --git a/modules/game_inventory/inventory.otui b/modules/game_inventory/inventory.otui index 4f404a04..4e1d4a72 100644 --- a/modules/game_inventory/inventory.otui +++ b/modules/game_inventory/inventory.otui @@ -4,7 +4,6 @@ UIWindow margin-top: 10 margin-left: 6 margin-right: 6 - move-policy: free updated Item // head diff --git a/src/otclient/const.h b/src/otclient/const.h index 775523d0..08fdfff6 100644 --- a/src/otclient/const.h +++ b/src/otclient/const.h @@ -211,7 +211,7 @@ namespace Otc }; enum ChaseModes { - StandWhileFighting = 0, + DontChase = 0, ChaseOpponent = 1 }; diff --git a/src/otclient/core/game.cpp b/src/otclient/core/game.cpp index 3a9fd83d..5e0014ed 100644 --- a/src/otclient/core/game.cpp +++ b/src/otclient/core/game.cpp @@ -77,6 +77,12 @@ void Game::processLogin(const LocalPlayerPtr& localPlayer, int serverBeat) m_localPlayer = localPlayer; m_serverBeat = serverBeat; + // synchronize fight modes with the server + m_fightMode = Otc::FightBalanced; + m_chaseMode = Otc::DontChase; + m_safeFight = true; + m_protocolGame->sendFightTatics(m_fightMode, m_chaseMode, m_safeFight); + // NOTE: the entire map description is not known yet g_lua.callGlobalField("Game", "onLogin", localPlayer); } @@ -384,6 +390,33 @@ void Game::move(const ThingPtr& thing, const Position& toPos, int count) m_protocolGame->sendThrow(thing->getPosition(), thing->getId(), thing->getStackpos(), toPos, count); } +void Game::setChaseMode(Otc::ChaseModes chaseMode) +{ + if(!isOnline() || !checkBotProtection()) + return; + + m_chaseMode = chaseMode; + m_protocolGame->sendFightTatics(m_fightMode, m_chaseMode, m_safeFight); +} + +void Game::setFightMode(Otc::FightModes fightMode) +{ + if(!isOnline() || !checkBotProtection()) + return; + + m_fightMode = fightMode; + m_protocolGame->sendFightTatics(m_fightMode, m_chaseMode, m_safeFight); +} + +void Game::setSafeFight(bool on) +{ + if(!isOnline() || !checkBotProtection()) + return; + + m_safeFight = on; + m_protocolGame->sendFightTatics(m_fightMode, m_chaseMode, m_safeFight); +} + void Game::attack(const CreaturePtr& creature) { if(!isOnline() || !creature || !checkBotProtection()) diff --git a/src/otclient/core/game.h b/src/otclient/core/game.h index 48b3fe23..6f83ca04 100644 --- a/src/otclient/core/game.h +++ b/src/otclient/core/game.h @@ -74,6 +74,14 @@ public: void useInventoryItemWith(int itemId, const ThingPtr& toThing); void move(const ThingPtr &thing, const Position& toPos, int count); + // fight tatics related + void setChaseMode(Otc::ChaseModes chaseMode); + void setFightMode(Otc::FightModes fightMode); + void setSafeFight(bool on); + Otc::ChaseModes getChaseMode() { return m_chaseMode; } + Otc::FightModes getFightMode() { return m_fightMode; } + bool isSafeFight() { return m_safeFight; } + // attack/follow related void attack(const CreaturePtr& creature); void cancelAttack(); @@ -124,6 +132,10 @@ private: ProtocolGamePtr m_protocolGame; bool m_dead; int m_serverBeat; + + Otc::FightModes m_fightMode; + Otc::ChaseModes m_chaseMode; + bool m_safeFight; }; extern Game g_game; diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index 0549ed0b..9a778363 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -204,6 +204,12 @@ void OTClient::registerLuaFunctions() g_lua.bindClassStaticFunction("turn", std::bind(&Game::turn, &g_game, _1)); g_lua.bindClassStaticFunction("walk", std::bind(&Game::walk, &g_game, _1)); g_lua.bindClassStaticFunction("forceWalk", std::bind(&Game::forceWalk, &g_game, _1)); + g_lua.bindClassStaticFunction("setChaseMode", std::bind(&Game::setChaseMode, &g_game, _1)); + g_lua.bindClassStaticFunction("setFightMode", std::bind(&Game::setFightMode, &g_game, _1)); + g_lua.bindClassStaticFunction("setSafeFight", std::bind(&Game::setSafeFight, &g_game, _1)); + g_lua.bindClassStaticFunction("getChaseMode", std::bind(&Game::getChaseMode, &g_game)); + g_lua.bindClassStaticFunction("getFightMode", std::bind(&Game::getFightMode, &g_game)); + g_lua.bindClassStaticFunction("isSafeFight", std::bind(&Game::isSafeFight, &g_game)); g_lua.bindClassStaticFunction("attack", std::bind(&Game::attack, &g_game, _1)); g_lua.bindClassStaticFunction("cancelAttack", std::bind(&Game::cancelAttack, &g_game)); g_lua.bindClassStaticFunction("follow", std::bind(&Game::follow, &g_game, _1));