ScriptUO
Scripting Resources & Utilities => Stealth Client => Stealth scripts => Topic started by: unisharp on October 02, 2020, 08:31:52 AM
-
SOURCE:
Located under repo https://github.com/unisharpUO/StealthUO-Scripts
- DancerDojo.py
- helpers.py
- py_stealth
DancerDojo Example:
This script will sit within given coordinates, use Honor virtue and kill Fan Dancers, alert when a player is near, use confidence when needed, use primary ability when plenty of mana is available, loot corpses for +20 splintering non-cursed non-antique weapons. It also insures the item.
Line 14 DancerDojo.py (commented)
# entrance 79, 97, 326, 344 - bloodyroom 104, 115, 640, 660
These are 2 different zone examples, the "bloody room" is like 3rd floor.
There are 2 coordinate checks:
Line 101 DancerDojo.py
if 79 <= GetX(_monsters[0]) <= 97 and\
326 <= GetY(_monsters[0]) <= 344:
This part tells the bot to only set targets to monsters within this range. If an already set target roams without this range, the bot will continue to follow it and kill it.
Line 128 DancerDojo.py
if 79 <= GetX(_corpse) <= 97 and\
326 <= GetY(_corpse) <= 344:
Unfortunatley if something roams out of the box and dies, it's not looted. I added this because someone was farming in a room near me and the bot would run over to him periodically and try and loot his corpses. This ensures that only corpses looted are those within the zone.
LOOTING:
This is rather easy to change.
def LootCorpse(_corpse):
UseObject(_corpse)
Wait(1500)
_lootList = NewFind([0xFFFF], [0xFFFF], [_corpse], True)
for _loot in _lootList:
_tooltipRec = GetTooltipRec(_loot)
if GetParam(_tooltipRec, 1112857) >= 20 and not\
ClilocIDExists(_tooltipRec, 1152714) and not\
ClilocIDExists(_tooltipRec, 1049643):
AddToSystemJournal(f'Looting Item: {_loot}')
MoveItem(_loot, 1, LootBag, 0, 0, 0)
InsureItem(_loot)
return
Those ClilocID's - 1112857, 11152714, 1049643 represent splintering, antique, cursed - respectively.
You can pull codes from here: https://github.com/unisharpUO/XScript/blob/6e885f0bb4b763d599b10ed0ca71e9b3e3da8aa1/XScript/Core/Attributes/WeaponAttributes.cs and here https://github.com/unisharpUO/XScript/blob/6e885f0bb4b763d599b10ed0ca71e9b3e3da8aa1/XScript/Core/Extensions/Extensions.cs and here https://github.com/unisharpUO/XScript/blob/6e885f0bb4b763d599b10ed0ca71e9b3e3da8aa1/XScript/Core/Attributes/MagicalAttributes.cs
With this information you should be able to easily create your own loot filters.
HEALING:
The only method I added was for confidence:
Line 115 DancerDojo.py
if GetHP(Self()) <= 90 and not Confidence:
Cast('Confidence')
Line 28 DancerDojo.py
def OnClilocSpeech(_param1, _param2, _param3, _message):
global Confidence
if 'exude' in _message:
Confidence = True
elif 'wanes' in _message:
Confidence = False
return
This checks for when confidence is actually up/down and will use confidence if it's not already up (and below 90 hp)
I'll add more areas upon request.
-
This is great. I've been hoping for a current, python based script and this has tons of different examples that could be used for different use cases in it. Thank you.
-
(https://media.giphy.com/media/gOkawaguYNiSI/giphy.gif)
-
commit pushed 10/13 - updated monster search
-
is possible to add section for loot jewelery with ssi or other atributes?
-
is possible to add section for loot jewelery with ssi or other atributes?
It's 100% possible with the short documentation posted above and a little bit of python knowledge. What are you having trouble with?
-
Let's break down the loot method
UseObject(_corpse)
Wait(1500)
Opens the corpse and waits (for the corpse to open, and using object timers)
_lootList = NewFind([0xFFFF], [0xFFFF], [_corpse], True)
Find every item on the corpse
for _loot in _lootList:
_tooltipRec = GetTooltipRec(_loot)
Loop through every item and get its tooltip records
if GetParam(_tooltipRec, 1112857) >= 20 and not\
ClilocIDExists(_tooltipRec, 1152714) and not\
ClilocIDExists(_tooltipRec, 1049643):
Each ClilocID represents a property on the item. Use the links in post 1 to determine what ClilocIDs you want to filter. This one in particular is filtering for 20 or greater splintering, not antique, not cursed
You can use 2 methods here: GetParam to get the property value of the ClilocID, if the property has a value. If the property has no value, such as Cursed or Brittle, then you can use ClilocIDExists.
AddToSystemJournal(f'Looting Item: {_loot}')
MoveItem(_loot, 1, LootBag, 0, 0, 0)
InsureItem(_loot)
Log the item in the system journal for notification, move the item to your loot bag and insure it.
With this information, you should be able to create your own loot filters.
UseObject(_corpse)
Wait(1500)
_lootList = NewFind([0xFFFF], [0xFFFF], [_corpse], True)
for _loot in _lootList:
_tooltipRec = GetTooltipRec(_loot)
if GetParam(_tooltipRec, 1060486) >= 10:
AddToSystemJournal(f'Looting Item: {_loot}')
MoveItem(_loot, 1, LootBag, 0, 0, 0)
InsureItem(_loot)
This will loot anything with 10 SSI or greater, for example.
-
Thank you for your answer. To loot every item I was edited by self. Its not very complicated.
But is possible that one parte of script looking for 20% weapon and second part of script looking for only jewelery ? with for example ssi and enchanced potions except cursed ?
in this part of code, script looking for any item. How change it to looking for jewels only ?
_lootList = NewFind([0xFFFF], [0xFFFF], [_corpse], True)
where i can find item id of rings bracelets like this ([0xFFFF]
For splintering weapon script work great. Sometimes i died but its normal.
With connection with easyuo gold looter + bag of sending its perfect.
You did good job.
-
Yes, you can do this with a bit of work. The problem is there is no pre-existing definition of armor types, weapon types, jewelry types, etc. You have to collect them and store them in an array.
What you'd need to do is collect every object type identifier and store them in an array, then you can use that in the find function:
ArmorTypes = [0x1415, 0x1416, 0x13db, 0x13e2]
_lootList = NewFind(ArmorTypes, [0xFFFF], [_corpse], True)
0x1415, 0x1416 = Plate Chest facing either direction
0x13db, 0x13e2 = Studded Chest facing either direction
etc...
To make things easier you can grab item types from either the ServUO Github repository or my XScript repo:
https://github.com/unisharpUO/XScript/blob/cd06adcb83a5626f5f9c51b1c9f2bca805628639/XScript/Distro/Items/Armor/BaseChest.cs
for example...
-
I remember jewelry pissing me off because I didn't want to make a list of every type ID, and I never could find a pattern in the name parameter that easily covered every ring & bracelet due to the magic prefix & suffix crap.
If you check parameters, like Unisharp is doing if GetParam(_tooltipRec, 1112857) >= 20 and not\
, but use it for both accepting and filtering properties you can end up selecting jewelry by making sure it doesn't have the strength requirement parameter. No jewelry will ever have that parameter.
So you can end up making loot lists like this.
"ssi jewelry": {
"props": {
"ssi 10": {"1060486": ["10"]},
"stam 8": {"1060484": ["8"]}
},
"filters": {
"antique": {"1152714": []},
"cursed": {"1049643": []},
"strength req": {"1061170": []}
}
}, },
-
There are not that many object types for jewelry...
We can see here...
https://github.com/unisharpUO/XScript/blob/cd06adcb83a5626f5f9c51b1c9f2bca805628639/XScript/Distro/Items/Jewels/BaseJewel.cs
[QueryType(typeof (BaseNecklace), typeof (BaseRing), typeof (BaseEarring), typeof (BaseBracelet))]
public class BaseJewel : Item, IJewel
BaseJewel has nested types BaseNecklace, BaseRing, BaseEarring, and BaseBracelet. All we need is BaseRing and BaseBracelet, so let's look at those....
https://github.com/unisharpUO/XScript/blob/cd06adcb83a5626f5f9c51b1c9f2bca805628639/XScript/Distro/Items/Jewels/Rings.cs
[QueryType(typeof (HumanRing), typeof (GargishRing))]
public class BaseRing : BaseJewel
BaseRing has nested types HumanRing and Gargish Ring....
[QuerySearch(new ushort[] {0x108A, 0x1F09})]
public class HumanRing : BaseRing
HumanRing has types 0x108A, 0x1F09
[QuerySearch(0x4212)]
public class GargishRing : BaseRing
GargishRing has types 0x4212
Rings = [0x108A, 0x1F09, 0x4212]
done
let's do bracelets now
https://github.com/unisharpUO/XScript/blob/cd06adcb83a5626f5f9c51b1c9f2bca805628639/XScript/Distro/Items/Jewels/Bracelet.cs
[QueryType(typeof (HumanBracelet), typeof (GargishBrace))]
public class BaseBracelet : BaseJewel
Same thing... HumanBracelet and GargishBrace
[QuerySearch(new ushort[] {0x1086, 0x1F06})]
public class HumanBracelet : BaseBracelet
[QuerySearch(0x4211)]
public class GargishBrace : BaseBracelet
Braclets = [0x1086, 0x1F06, 0x4211]
now combine them
Jewlery = [0x108A, 0x1F09, 0x4212, 0x1086, 0x1F06, 0x4211]
Now you have a set of jewelry types to search for.
It's just going to be harder with armor/weapons because there are more types.
There are now links in this thread that will help you:
- Find the required ClilocIDs needed for parsing parameters
- Find object types to parse
-
"It's just going to be harder with armor/weapons because there are more types." <== This sums up the whole problem. You start doing it for one type, then you start doing it for everything. You are right though, since the more complex the script gets, the more likely you will need a giant list of all the type IDs.
-
Thx for answers.
Im not programmer so is hard to edit for me.
im tried something like this. Client not showing error but script not loot rings not cursed enhancepotions 20+
Part with loot looks like this. Im trying many combinations _loot, _lootlist1, _loot, lootlist, etc. but not work. (part with splintering work well)
def LootCorpse(_corpse):
UseObject(_corpse)
Wait(1500)
_lootList = NewFind([0xFFFF], [0xFFFF], [_corpse], True)
for _loot in _lootList:
_tooltipRec = GetTooltipRec(_loot)
if GetParam(_tooltipRec, 1112857) >= 20 and not\
ClilocIDExists(_tooltipRec, 1152714) and not\
ClilocIDExists(_tooltipRec, 1049643):
AddToSystemJournal(f'Looting Item: {_loot}')
MoveItem(_loot, 1, LootBag, 0, 0, 0)
InsureItem(_loot)
_lootList1 = NewFind([0x108A, 0x1F09, 0x4212, 0x1086, 0x1F06, 0x4211], [0x108A, 0x1F09, 0x4212, 0x1086, 0x1F06, 0x4211], [_corpse], True)
for _loot1 in _lootList1:
_tooltipRec = GetTooltipRec(_loot1)
if GetParam(_tooltipRec, 1060411) >= 20 and not\
ClilocIDExists(_tooltipRec, 1049643):
AddToSystemJournal(f'Looting Item: {_loot}')
MoveItem(_loot1, 1, LootBag, 0, 0, 0)
InsureItem(_loot1)
return
if is not problem for you, could you show me how to edit this without programing knowlege ?
My another proposition is add to this script gold looter with automatic send when it reach 95% max weight by "bag of sending"
With this addons your script will be total afk gold and item farmer :) But i dont know if is possible.
Waiting for your reply.
Merry Christmas!
-
_lootList1 = NewFind([0x108A, 0x1F09, 0x4212, 0x1086, 0x1F06, 0x4211], [0xFFFF], [_corpse], True)
Merry Christmas
NewFind(Array of types, Array of colors, Array of containers, Search Subcontainers?)
0xFFFF specifies anything/everything.
-
_lootList1 = NewFind([0x108A, 0x1F09, 0x4212, 0x1086, 0x1F06, 0x4211], [0xFFFF], [_corpse], True)
Merry Christmas
NewFind(Array of types, Array of colors, Array of containers, Search Subcontainers?)
0xFFFF specifies anything/everything.
It is work!! Thanks :)
-
I'll make a snippet example for gold/sending in another thread when it's ready.
-
12-21-20 Changes:
- If bag of sending exists in backpack, enable good looting
- If weight is equal to or over limit, send gold to bank
Commits:
https://github.com/unisharpUO/StealthUO-Scripts/commit/8222629a4fabbd68fbccf6a5ff77e07a805c7714
https://github.com/unisharpUO/StealthUO-Scripts/commit/9cb81e70c2f2e25cceb28cab1fe8aef4839f80b3
-
i need to change name of sending bag to
if __name__ == '__main__':
global BagofSendingBag
but still not looting gold to backpack from corpose.
-
i need to change name of sending bag to
if __name__ == '__main__':
global BagofSendingBag
but still not looting gold to backpack from corpose.
Just remove that delete that line alltogether
delete 'global BafofSendingBag'
-
i have errors.
22:41:25:992 []: Traceback (most recent call last):
22:41:25:994 []: File "C:\Users\pc\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 197, in _run_module_as_main
22:41:25:994 []: return _run_code(code, main_globals, None,
22:41:25:995 []: File "C:\Users\pc\AppData\Local\Programs\Python\Python39\lib\runpy.py", line 87, in _run_code
22:41:25:995 []: exec(code, run_globals)
22:41:25:996 []: File "C:\Users\pc\Desktop\stelth\py_stealth\__main__.py", line 80, in <module>
22:41:25:998 []: main()
22:41:25:998 []: File "C:\Users\pc\Desktop\stelth\py_stealth\__main__.py", line 59, in main
22:41:25:999 []: module = __import__(os.path.splitext(filename)[0])
22:41:25:999 []: File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
22:41:26:000 []: File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
22:41:26:001 []: File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
22:41:26:002 []: File "C:\Users\pc\Desktop\stelth\py_stealth\py34.py", line 33, in exec_module
22:41:26:003 []: exec(code, module.__dict__)
22:41:26:004 []: File "C:\Users\pc\Desktop\DancerDojo.py", line 167, in <module>
22:41:26:004 []: LootCorpse(_corpse)
22:41:26:005 []: File "C:\Users\pc\Desktop\DancerDojo.py", line 55, in LootCorpse
22:41:26:005 []: _count = Count(_loot)
22:41:26:007 []: File "C:\Users\pc\Desktop\stelth\py_stealth\methods.py", line 3022, in Count
22:41:26:008 []: FindType(ObjType, Backpack())
22:41:26:008 []: File "C:\Users\pc\Desktop\stelth\py_stealth\methods.py", line 1480, in FindType
22:41:26:010 []: return _find_graphic(ObjType, 0xFFFF, Container, False)
22:41:26:011 []: File "C:\Users\pc\Desktop\stelth\py_stealth\_protocol.py", line 171, in __call__
22:41:26:011 []: data += cls(val).serialize()
22:41:26:012 []: File "C:\Users\pc\Desktop\stelth\py_stealth\_datatypes.py", line 32, in serialize
22:41:26:014 []: return struct.pack(self.fmt, self)
22:41:26:015 []: struct.error: ushort format requires 0 <= number <= 0xffff
and this is my whole script.
from py_stealth import *
from helpers import *
from datetime import datetime
Confidence = False
FanDancer = 0x0F7
Corpse = 0x2006
LootBag = 0
SendingBag = 0
PlayerTypes = [183, 184, 185, 186, 400, 401, 402, 403, 605, 606, 607, 608, 666,
667, 694, 695, 750, 751, 970]
# entrance 79, 97, 326, 344 - bloodyroom 104, 115, 640, 660
def OnDrawObject(_objID):
if _objID != Self():
if GetType(_objID) in PlayerTypes:
_tooltipRec = GetTooltipRec(_objID)
if len(_tooltipRec) > 0:
if _tooltipRec[0]['Cliloc_ID'] == 1050045:
_name = _tooltipRec[0]['Params'][1]
_now = datetime.now()
_now = _now.strftime("%m/%d/%Y %H:%M:%S")
AddToSystemJournal(f'Player Found: {_name} at {_now}')
return
def OnClilocSpeech(_param1, _param2, _param3, _message):
global Confidence
if 'exude' in _message:
Confidence = True
elif 'wanes' in _message:
Confidence = False
return
def CheckWeight():
if (Weight() >= MaxWeight()) and (SendingBag != 0):
if FindTypeEx(0x0EED, 0xFFFF, Backpack(), True):
_gold = GetFoundList()
UseObject(SendingBag)
Wait(1500)
WaitTargetObject(_gold[0])
else:
AddToSystemJournal("I'm overweight and I can't find gold to send..")
def LootCorpse(_corpse):
UseObject(_corpse)
Wait(1500)
_lootList = NewFind([0xFFFF], [0xFFFF], [_corpse], True)
for _loot in _lootList:
if (GetType(_loot) == 0x0EED) and (SendingBag != 0):
_count = Count(_loot)
MoveItem(_loot, _count, LootBag, 0, 0, 0)
else:
_tooltipRec = GetTooltipRec(_loot)
if GetParam(_tooltipRec, 1112857) >= 20 and not\
ClilocIDExists(_tooltipRec, 1152714) and not\
ClilocIDExists(_tooltipRec, 1049643):
AddToSystemJournal(f'Looting Item: {_loot}')
MoveItem(_loot, 1, LootBag, 0, 0, 0)
InsureItem(_loot)
_lootList1 = NewFind([0x108A, 0x1F09, 0x4212, 0x1086, 0x1F06, 0x4211], [0xFFFF], [_corpse], True)
for _loot1 in _lootList1:
_tooltipRec = GetTooltipRec(_loot1)
if GetParam(_tooltipRec, 1060411) >= 20 and not\
ClilocIDExists(_tooltipRec, 1049643):
AddToSystemJournal(f'Looting Item: {_loot1}')
MoveItem(_loot1, 1, LootBag, 0, 0, 0)
InsureItem(_loot1)
return
def InsureItem(_item):
Wait(250)
RequestContextMenu(Self())
_i = 0
for _menuItem in GetContextMenu().splitlines():
if "Toggle Item Insurance" in _menuItem:
SetContextMenuHook(Self(), _i)
Wait(250)
WaitTargetObject(_item)
Wait(250)
CancelMenu()
else:
_i += 1
AddToSystemJournal("Couldn't find insure menu item.")
CancelAllMenuHooks()
CancelTarget()
return
if __name__ == '__main__':
SetEventProc('evclilocspeech', OnClilocSpeech)
SetEventProc('evdrawobject', OnDrawObject)
SetFindDistance(20)
SetFindVertical(20)
SetDropDelay(850)
UseObject(Backpack())
Wait(850)
if FindTypesArrayEx([0x0E76], [0xFFFF], [Backpack()], True):
_bags = GetFindedList()
for _bag in _bags:
# make sure they are bags of sending
if 'sending' in GetTooltip(_bag).split('|')[0]:
AddToSystemJournal("Found bag of sending...")
SendingBag = _bag
Wait(850)
_ignoreList = NewFind([0xFFFF], [0xFFFF], [Backpack()], True)
for _ignoreItem in _ignoreList:
Ignore(_ignoreItem)
AddToSystemJournal('Target your loot bag...')
LootBag = RequestTarget()
UseObject(LootBag)
_monsters = []
_corpses = []
_currentTarget = 0
while True:
ClearBadLocationList()
while not Connected():
Connect()
Wait(10000)
CheckWeight()
_monsters = NewFind([FanDancer], [0xFFFF], [0x0], False)
# entrance 79, 97, 326, 344 - bloodyroom 104, 115, 640, 660
if (_currentTarget == 0 and len(_monsters) > 0) or\
(len(_monsters) > 0 and _currentTarget != 0 and
not IsObjectExists(_currentTarget)):
if 79 <= GetX(_monsters[0]) <= 97 and\
326 <= GetY(_monsters[0]) <= 344:
_currentTarget = _monsters[0]
AddToSystemJournal(f'Current Target: {_currentTarget}')
ReqVirtuesGump()
UseVirtue('honor')
WaitTargetObject(_currentTarget)
Attack(_currentTarget)
if _currentTarget != 0 and IsObjectExists(_currentTarget):
NewMoveXY(GetX(_currentTarget), GetY(_currentTarget), False, 1,
True)
Attack(_currentTarget)
if GetHP(Self()) <= 90 and not Confidence:
Cast('Confidence')
if GetMana(Self()) >= 40:
UsePrimaryAbility()
_corpses = NewFind([Corpse], [0xFFFF], [0x0], False)
if len(_corpses) > 0:
for _corpse in _corpses:
if GetDistance(_corpse) < 3:
LootCorpse(_corpse)
Ignore(_corpse)
else:
if 79 <= GetX(_corpse) <= 97 and\
326 <= GetY(_corpse) <= 344:
NewMoveXY(GetX(_corpse), GetY(_corpse), True, 0, True)
LootCorpse(_corpse)
Ignore(_corpse)
Wait(1000)
-
12/22/20 - Updated Find methods, added corpse ignore list, fixed quantity error
- Tested
Commit pushed to Github
-
Tested! Work!
Big Thanks :)