if (not gDisabledPlugins.moblist) then kMobList_CatW = 100 kMobList_CatItemH = 16 kMobList_CatItemBarH = 5 kMobList_CatItemBarYOff = 4 kMobList_CatDist = 0 kMoblist_npc_titles = { ["[HEALERw]"] = " the wandering healer", ["[HEALER]"] = " the healer", ["[ESCORT]"] = " the seeker of adventure", ["[BSMITH]"] = " the blacksmith", ["[ASMITH]"] = " the armorsmith", ["[WSMITH]"] = " the weaponsmith", ["[TAIL]"] = " the tailor", ["[WEAV]"] = " the weaver", ["[TANN]"] = " the tanner", ["[FUR]"] = " the furtrader", ["[TINK]"] = " the tinker", ["[CARP]"] = " the carpenter", ["[ARCH]"] = " the architect", ["[BOW]"] = " the bowyer", ["[ESTA]"] = " the real estate broker", ["[HAIR]"] = " the hairstylist", ["[PROV]"] = " the provisioner", ["[COBB]"] = " the cobbler", ["[ALCH]"] = " the alchemist", ["[HERB]"] = " the herbalist", ["[NEWS]"] = " the town crier", ["[BANK]"] = " the banker", ["[MINT]"] = " the minter", ["[INN]"] = " the innkeeper", ["[JEWEL]"] = " the jeweler", ["[AUCTION]"] = " the Auctioner", } kMainTargetListMarkerOffX = -7 kMainTargetListMarkerOffY = -2 kMobListCat_Self = 1 kMobListCat_Friends = 2 kMobListCat_Players = 3 kMobListCat_Pets = 4 kMobListCat_Rest = 5 kMobList_MaxCat = kMobListCat_Rest gSpellCastRange = 12 if (not cUOMobList) then cUOMobList = RegisterWidgetClass("UOMobList") cUOMobListItem = RegisterWidgetClass("UOMobListItem") gMobListNameShortCuts = { ["deathwatch beetle hatchling"] = "dwb-hatchling", ["DeathWatch Beetle hatchling"] = "DWB-Hatchling", } RegisterListener("Hook_Window_Resize",function (vw,vh) if (gMobList) then gMobList:Reposition(vw,vh) end end) RegisterListener("Hook_PostLoad",function () gMobList = GetDesktopWidget():CreateChild("UOMobList") end) RegisterListener("Hook_AttackReqSend",function (serial) SelectMobile(serial) end) RegisterListener("Hook_SelectMobile",function (serial) MobListSetMainTargetSerial(serial) end) end function cUOMobList:Reposition (vw,vh) self:SetPos(vw-kMobList_CatW,230) end function cUOMobList:Init (parentwidget,params) self:InitAsGroup(parentwidget,params) self.items = {} self.partyWidgetList = {} self.uoamWidgetList = {} self.catgroup = {} for i=1,kMobList_MaxCat do self.catgroup[i] = self:CreateChild("Group") end self.gfx_maintarget_listmarker = self:CreateChild("UOText",{x=0,y=0,text=">",col={r=1,g=0,b=0},bold=true}) self.gfx_maintarget_listmarker:SetVisible(false) self.gfx_maintarget_listmarker2 = self:CreateChild("UOText",{x=0,y=0,text=">",col={r=0,g=0,b=1},bold=true}) self.gfx_maintarget_listmarker2:SetVisible(false) self.gfx_maintarget = gRootWidget.tooltip:CreateChild("UOText",{x=0,y=0,text="",col={r=1,g=0,b=0},bold=true,html=true}) self.gfx_maintarget_line = gRootWidget.tooltip:CreateChild("LineList",{matname="BaseWhiteNoLighting",bDynamic=true,r=1,g=0,b=0}) local vw,vh = GetViewportSize() self:Reposition(vw,vh) RegisterListener("Hook_HUDStep", function () self:Step() end) RegisterListener("Hook_MobName", function (serial,name,clilocid) self:MobName(serial,name,clilocid) end) -- from several text/speak packets.. RegisterListener("Hook_ToolTipUpdate", function (serial) self:ToolTipUpdate(serial) self:UpdatePartyNameTooltip(serial) end) RegisterListener("Hook_LabelUpdate", function (serial) self:ToolTipUpdate(serial) self:UpdatePartyNameTooltip(serial) end) RegisterListener("Hook_Object_CreateMobile", function (mobile) self:AddMob(mobile) end) RegisterListener("Hook_Object_DestroyMobile", function (mobile) self:RemoveMob(mobile) end) RegisterListener("Hook_UpdatePartyMemberList", function () print("moblist:Hook_UpdatePartyMemberList") self:RecalcCat() self:UpdatePartyMemberList() self:UpdateAllNameGfx() end) RegisterListener("Hook_UOAM_PosUpdate", function () self:UOAMUpdate() end) end function cUOMobList:UpdatePartyNameTooltip (serial) local widget = self.partyWidgetList[serial] if (not widget) then return end widget.name = MobListShortenName(GetItemTooltipOrLabel(serial) or "???+") widget:SetUOHtml(widget.name,true) end function cUOMobList:UpdatePartyMemberList () local partylist = GetPartyMemberList() -- {[serial]=true,...} local partyWidgetList = self.partyWidgetList for serial,v in pairs(partylist) do local widget = partyWidgetList[serial] if ((not widget) and serial ~= GetPlayerSerial()) then local name = MobListShortenName(GetItemTooltipOrLabel(serial) or "???#") widget = gRootWidget.tooltip:CreateChild("UOText",{x=0,y=0,text=name,col={r=0,g=1,b=0},bold=true,html=true}) widget.name = name partyWidgetList[serial] = widget end end for serial,widget in pairs(partyWidgetList) do if (not partylist[serial]) then -- left party widget:Destroy() partyWidgetList[serial] = nil end end end function cUOMobList:StepPartyMarkers () for serial,widget in pairs(self.partyWidgetList) do local xloc,yloc,iFacet,bIsOnSameFacet = PartySystem_GetMemberPos(serial) local zloc = gPlayerZLoc or 0 if (xloc) then local px,py = gCurrentRenderer:UOPosToPixelPos(xloc,yloc,zloc) local w,h = widget:GetSize() local minx,miny,maxx,maxy = 0,64,gViewportW-160,gViewportH-32 local x = max(minx,min(maxx-w,(px or 0)-0.5*w)) local y = max(miny,min(maxy-h,(py or 0))) widget:SetPos(x,y) end if (widget.oldbIsOnSameFacet ~= bIsOnSameFacet) then widget.oldbIsOnSameFacet = bIsOnSameFacet widget.params.col = bIsOnSameFacet and {r=0,g=1,b=0} or {r=0.5,g=0.5,b=0.5} widget:SetUOHtml(widget.name,true) end end end -- triggered when uoam-data-packet is received function cUOMobList:UOAMUpdate () local uoamWidgetList = self.uoamWidgetList local uoamPosList = UOAM_GetOtherPositions() for name,data in pairs(uoamPosList) do -- {xloc=?,yloc=?,bIsOnSameFacet=?} local widget = uoamWidgetList[name] if (not widget) then widget = gRootWidget.tooltip:CreateChild("UOText",{x=0,y=0,text=name,col={r=0,g=1,b=0},bold=true,html=true}) uoamWidgetList[name] = widget end widget.xloc,widget.yloc = data.xloc,data.yloc widget.bIsOnSameFacet = data.bIsOnSameFacet end for name,widget in pairs(uoamWidgetList) do if (not uoamPosList[name]) then -- logged out widget:Destroy() uoamWidgetList[name] = nil end end end -- every frame function cUOMobList:UOAMStep () for name,widget in pairs(self.uoamWidgetList) do -- {xloc=?,yloc=?,bIsOnSameFacet=?} local xloc,yloc,zloc = widget.xloc,widget.yloc,(gPlayerZLoc or 0) local px,py = gCurrentRenderer:UOPosToPixelPos(xloc,yloc,zloc) local w,h = widget:GetSize() local minx,miny,maxx,maxy = 0,64,gViewportW-160,gViewportH-32 local x = max(minx,min(maxx-w,(px or 0)-0.5*w)) local y = max(miny,min(maxy-h,(py or 0))) widget:SetPos(x,y) if (widget.oldbIsOnSameFacet ~= widget.bIsOnSameFacet) then widget.oldbIsOnSameFacet = widget.bIsOnSameFacet widget.params.col = widget.bIsOnSameFacet and {r=0,g=0.5,b=0} or {r=0.5,g=0.5,b=0.5} widget:SetUOHtml(name,true) end end end function cUOMobList:ToolTipUpdate (serial) local mobile = GetMobile(serial) local item = mobile and mobile.moblist_item if (item) then item:UpdateName() end end function cUOMobList:MobName (serial,name,clilocid) local mobile = GetMobile(serial) local item = mobile and mobile.moblist_item if (item and (not item.lowname)) then item:UpdateName(name,clilocid) end end function cUOMobList:AddMob (mobile) self.bNeedsReGroup = true local item = self:CreateChild("UOMobListItem",{serial=mobile.serial,mobile=mobile,moblist=self}) mobile.moblist_item = item self.items[item] = true end function cUOMobList:RemoveMob (mobile) local item = mobile.moblist_item if (not item) then return end mobile.moblist_item = nil self.items[item] = nil item:Destroy() self.bNeedsReGroup = true end function cUOMobList:RecalcCat () for item,v in pairs(self.items) do item:RecalcCat() end end function cUOMobList:UpdateAllNames () for item,v in pairs(self.items) do item.old_fulltext = nil item:UpdateName() end end function cUOMobList:UpdateMainTargetListMarker () if (self.maintarget_serial) then local mobile = GetMobile(self.maintarget_serial) local moblist_item = mobile and mobile.moblist_item if (moblist_item) then local ax,ay = moblist_item:GetDerivedPos() local bx,by = self:GetDerivedPos() local y = ay-by self.gfx_maintarget_listmarker:SetVisible(true) self.gfx_maintarget_listmarker:SetPos(kMainTargetListMarkerOffX,kMainTargetListMarkerOffY+y) else self.gfx_maintarget_listmarker:SetVisible(false) end else self.gfx_maintarget_listmarker:SetVisible(false) end end function cUOMobList:UpdateSmartTargetIndicator () local serial = MacroCmd_GetSmartTargetForLastSpell() local ypos = nil if (serial) then local mobile = GetMobile(serial) local moblist_item = mobile and mobile.moblist_item if (moblist_item) then local ax,ay = moblist_item:GetDerivedPos() local bx,by = self:GetDerivedPos() ypos = ay-by end end -- only update if changed if (self.mySmartTargetIndicator_lastypos ~= ypos) then self.mySmartTargetIndicator_lastypos = ypos if (ypos) then self.gfx_maintarget_listmarker2:SetVisible(true) self.gfx_maintarget_listmarker2:SetPos(kMainTargetListMarkerOffX-5,kMainTargetListMarkerOffY+ypos) else self.gfx_maintarget_listmarker2:SetVisible(false) end end end function cUOMobList:SetMainTarget (serial,name) if (serial == 0 or serial == GetPlayerSerial() or serial == self.maintarget_serial) then serial = nil end if (serial and (not IsOrWasMobile(serial))) then return end self.maintarget_serial = serial self:UpdateMainTargetListMarker() --~ print("UOMobList:SetMainTarget",serial,name) local gfx = self.gfx_maintarget local gfx2 = self.gfx_maintarget_line if (self.maintarget_serial) then gfx:SetVisible(true) gfx2:SetVisible(true) name = name or MobListShortenName(GetItemTooltipOrLabel(serial) or "???") local r,g,b = 1,1,1 local mobile = GetMobile(serial) local notoriety = mobile and mobile.notoriety if (notoriety) then r,g,b = GetNotorietyColor(notoriety) end gfx:SetCol(r,g,b) gfx:SetUOHtml(name,true) MacroSetLastTarget(serial) else gfx:SetVisible(false) gfx2:SetVisible(false) end end function cUOMobList:UpdateAllNameGfx () for item,v in pairs(self.items) do item:UpdateNameGfx() end end function cUOMobList:Step () if (self.bNeedsReGroup) then self.bNeedsReGroup = false for k,group in pairs(self.catgroup) do group.itemcount = 0 end for item,v in pairs(self.items) do item:ReGroup(self.catgroup) end -- reposition groups local y = 0 for k,group in ipairs(self.catgroup) do group:SetPos(0,y) y = y + kMobList_CatItemH * group.itemcount + ((group.itemcount > 0) and kMobList_CatDist or 0) end self:UpdateMainTargetListMarker() end for item,v in pairs(self.items) do item:Step() end -- uoam-name-widgets self:UOAMStep() self:StepPartyMarkers() self:UpdateSmartTargetIndicator() -- maintarget text : update position on screen if (self.maintarget_serial) then local mobile = GetMobile(self.maintarget_serial) local xloc,yloc,zloc,notoriety local bInRange = true if (mobile) then xloc,yloc,zloc = gCurrentRenderer:GetExactMobilePos(mobile) notoriety = mobile.notoriety self.maintarget_last_xloc = xloc self.maintarget_last_yloc = yloc self.maintarget_last_zloc = zloc self.maintarget_last_notoriety = notoriety else bInRange = false xloc = self.maintarget_last_xloc or 0 yloc = self.maintarget_last_yloc or 0 zloc = self.maintarget_last_zloc or 0 notoriety = self.maintarget_last_notoriety or 0 end local zadd = 10 local gfx = self.gfx_maintarget local gfx2 = self.gfx_maintarget_line local px,py = gCurrentRenderer:UOPosToPixelPos(xloc,yloc,zloc) local w,h = gfx:GetSize() local minx,miny,maxx,maxy = 0,64,gViewportW-160,gViewportH-32 local x = max(minx,min(maxx-w,(px or 0)-0.5*w)) local y = max(miny,min(maxy-h,(py or 0))) gfx:SetPos(x,y) local f = 0.5 -- bigger -> longer line local fi = 1 - f local x = max(minx,min(maxx,(px or 0))) local y = max(miny,min(maxy,(py or 0))) local x2 = x*fi + f*gViewportW*0.5 local y2 = y*fi + f*gViewportH*0.5 local r,g,b = GetNotorietyColor(notoriety) local brightness = 1 if (IsOutsideRange(xloc,yloc,gPlayerXLoc,gPlayerYLoc,gSpellCastRange)) then brightness = 0.3 end if (not bInRange) then brightness = 0.1 end gfx2:SetColParam(r*brightness,g*brightness,b*brightness) gfx2:SetLineList({{x2,y2,0,x,y,0}}) end end -- ***** ***** ***** ***** ***** UOMobListItem function cUOMobListItem:Init (parentwidget,params) self:InitAsGroup(parentwidget,params) self:SetIgnoreBBoxHit(false) self:SetConsumeChildHit(true) self.serial = params.serial self.mobile = params.mobile self.moblist = params.moblist self.text = self:CreateChild("UOText",{x=0,y=0,text="",col={r=1,g=1,b=1},fontid=2,bold=true,html=true}) self.text:SetIgnoreBBoxHit(false) self.bNameUnknown = true local mobile = params.mobile local w,h = kMobList_CatW,kMobList_CatItemBarH local xoff,yoff = 0,kMobList_CatItemH+kMobList_CatItemBarYOff-kMobList_CatItemBarH self.fillw = w self.fillh = h local paramb = MakeSpritePanelParam_BorderPartMatrix(GetPlainTextureGUIMat("simplebutton.png"),w,h, xoff,yoff, 0,0, 4,8,4, 4,8,4, 32,32, 1,1, false, false) local paramf = MakeSpritePanelParam_BorderPartMatrix(GetPlainTextureGUIMat("simplebutton.png"),w,h, xoff,yoff, 0,0, 4,8,4, 4,8,4, 32,32, 1,1, false, false) paramb.r,paramb.g,paramb.b = 1,0,0 self.border = self:CreateChild("Image",{gfxparam_init=paramb}) self.fill = self:CreateChild("Image",{gfxparam_init=paramf,bVertexBufferDynamic=true}) self:UpdateName() self:RecalcCat() end function MobListShortenName (text) return UOShortenName(text) end function cUOMobListItem:on_mouse_left_drag_start () if (self.mobile and gKeyPressed[key_lalt]) then local widget = OpenHealthbarAtMouse(self.mobile) if (widget) then widget:BringToFront() widget:StartMouseMove() end end end function cUOMobListItem:UpdateName(name,clilocid) if (name and (not self.lowname)) then self.lowname = name self.namecliloc = clilocid end local tooltip = GetItemTooltipOrLabel(self.serial) local text = tooltip or self.lowname self.bNameUnknown = false if (not text) then self.bNameUnknown = true text = "unknown" end local bNameUpdate = false if (self.old_fulltext ~= text) then self.old_fulltext = text bNameUpdate = true local fulltext = text text = MobListShortenName(text) --~ print("UOMobListItem:UpdateName","#"..(text or "").."#") text = gMobListNameShortCuts[text] or text -- npcs friends self.bIsNPC = false if (StringContains(text,"guildmaster")) then text = "[GUILD]"..string.gsub(text,"guildmaster","") end for k,v in pairs(kMoblist_npc_titles) do if (StringContains(text,v)) then self.bIsNPC = true text = k..string.gsub(text,v,"") end end local labelhue = GetItemLabelHue(self.serial) if (labelhue == kPlayerVendorLabelHue) then self.bIsNPC = true end text = string.gsub(text,"^([^%[%]]+)(%[.+%])","%2%1") self.old_text = text -- check friends self.bIsFriendlyGuild = false for k,guildtag in pairs(gFriendlyGuildTags) do if (StringContains(text,guildtag)) then self.bIsFriendlyGuild = true break end end --~ if (StringContains(text,"hazk")) then print("ghaz:",self.bIsFriendlyGuild) end -- check pets self.bIsPet = StringContains(fulltext,"(summoned)") or StringContains(fulltext,"(tame)") local mobile = self.mobile if (mobile.artid == 574 and mobile.hue == 0) then self.bIsPet = true end -- blade spirit if (mobile.artid == 164 and mobile.hue == 0) then self.bIsPet = true end -- energy vortex end self:RecalcCat() if (bNameUpdate) then self:UpdateNameGfx() end end function cUOMobListItem:UpdateNameGfx() local mobile = self.mobile local serial = self.serial local r,g,b = GetNotorietyColor(mobile.notoriety) local labelhue = GetItemLabelHue(serial) if (labelhue == kPlayerVendorLabelHue) then r,g,b = 0,1,1 end self.text.params.col = {r=r,g=g,b=b} local text = self.old_text --~ print("moblist:UpdateNameGfx",serial,IsMobileInParty(serial),text) if (labelhue) then r,g,b = GetHueColor(labelhue-1) end text = sprintf("",floor(r*255),floor(g*255),floor(b*255)).."+"..""..text if (IsMobileInParty(serial)) then text = "#"..text end self.text:SetUOHtml(text,true) -- .." "..self.cat end function cUOMobListItem:SetSelfAsMainTarget () self.moblist:SetMainTarget(self.serial,self.old_text or "???") end function cUOMobListItem:Step () local mobile = self.mobile if (self.old_notoriety ~= mobile.notoriety) then self.old_notoriety = mobile.notoriety self:RecalcCat() self:UpdateNameGfx() -- todo : update bar-background color ? not visible when full hp ? end -- healthbar color local r,g,b = 0,0.5,1 -- blue if (IsMobilePoisoned(mobile)) then r,g,b = 0,0.5,0 end if (IsMobileMortaled(mobile)) then r,g,b = 1,1,0 end local gfxparam = self.fill.params.gfxparam_init gfxparam.r = r gfxparam.g = g gfxparam.b = b -- healthbar size local f_hp = mobile:GetRelHP() or 1 self.fill:SetSize(max(0,min(1,f_hp)) * self.fillw,self.fillh) end function cUOMobListItem:RecalcCat () local serial = self.serial local mobile = self.mobile local notoriety = mobile.notoriety --~ kNotoriety_Friend = 2 -- friend (necro familiar,pets) --~ kNotoriety_Red = 6 -- murderer (summons,evortex) --~ print("moblist:RecalcCat",serial,"party:",IsMobileInParty(serial),self.old_text) if (self.bNameUnknown) then return self:SetCat(kMobListCat_Rest) end if (GetPlayerSerial() == serial) then return self:SetCat(kMobListCat_Self) end if (IsMobileInParty(serial) or self.bIsFriendlyGuild) then return self:SetCat(kMobListCat_Friends) end if (self.bIsPet) then return self:SetCat(kMobListCat_Pets) end if (self.namecliloc) then if (notoriety == kNotoriety_Friend) then return self:SetCat(kMobListCat_Pets) end local bIsHuman = mobile.artid == 400 or mobile.artid == 401 -- red humands like brigards,cannibals,ronins,ninjas... if (notoriety == kNotoriety_Red and (not bIsHuman)) then return self:SetCat(kMobListCat_Pets) end -- evortex,undead.. end if (self.namecliloc or self.bIsNPC or notoriety == kNotoriety_Neutral) then return self:SetCat(kMobListCat_Rest) end if (notoriety == kNotoriety_Friend) then return self:SetCat(kMobListCat_Friends) end if (notoriety == kNotoriety_Invul) then return self:SetCat(kMobListCat_Rest) end return self:SetCat(kMobListCat_Players) end function cUOMobListItem:SetCat (cat) --~ local mobile = self.mobile --~ local notoriety = mobile.notoriety --~ print("cUOMobListItem:SetCat",cat,notoriety,GetItemTooltipOrLabel(self.serial)) if (self.cat == cat) then return end if (cat == kMobListCat_Players) then NotifyListener("Hook_Moblist_NewPlayer",self.mobile,self.old_text) end self.cat = cat self.params.moblist.bNeedsReGroup = true self:UpdateNameGfx() end function cUOMobListItem:ReGroup (catgrouplist) local catindex = self.cat or 1 local group = catgrouplist[catindex] local mypos = group.itemcount self:SetParent(group) self:SetPos(0,kMobList_CatItemH * mypos) group.itemcount = group.itemcount + 1 end -- not needed anymore, now in IrisLeftClickDown() --~ function cUOMobListItem:on_mouse_left_down () if (not IsTargetModeActive()) then self:SetSelfAsMainTarget() end end -- ***** ***** ***** ***** ***** rest function MobListGetMainTargetSerial() return gMobList and gMobList.maintarget_serial end function MobListSetMainTargetSerial(serial) gMobList:SetMainTarget(serial) end end