SeedClipMod
Contents
How To Add To Mod
- copy the contents of the scriptcommands_UI_info override file
- create a new file in your mods scripts directory named scriptcommands_UI_info.lua
- paste the contents of override file and click save.
- reload your server and your ready to go.
Advanced Options
- if you are looking for the code for clipping its at the bottom of the override file posted
- there is an example for recognizing simple_mob_spawners and formatting special data elements
- could move all the functions to a user interface window that displays a group table populated with these objects and do 1 giant group clip
Example Outpot of the Seed Clip
when you click SeedClip from the info button on any object you get the following XML output on the clip board for pasting into your seedobjects.xml file
<DynamicObject>
<ObjectCreationParams>tent_goblin 747.59057617188 0 1742.8210449219 0 130.90209960938 0 0.80000001192093 0.80000001192093 0.80000001192093</ObjectCreationParams>
</DynamicObject>
when you use the SeedClip button on a simple_mob_spawner you get the following XML output on the clipboard for pasting into your seedobjects.xml file. It also applies the needed elements for controlling the spawn template, delay, amount to spawn, radius all set at defaults.
<DynamicObject>
<ObjectCreationParams>simple_mob_spawner 643.80731201172 0 1682.2386474609 0 0 0 1 1 1</ObjectCreationParams>
<ObjVarOverrides>
<StringVariable Name="spawnTemplate">template</StringVariable>
<DoubleVariable Name="spawnDelay">300</DoubleVariable>
<DoubleVariable Name="spawnCount">1</DoubleVariable>
<DoubleVariable Name="spawnRadius">0</DoubleVariable>
</ObjVarOverrides>
</DynamicObject>
scriptcommands_UI_info.lua override file
require 'default:scriptcommands_UI_info'
-----------------------------------------------------------------
-- MOD FOR QUICK EDITING OF DYNAMIC OBJECTS IN THE GAME
-----------------------------------------------------------------
-- This mod adds a button to the /info UI called Seed Clip
-- when you click this button it will gather all the data needed
-- the object and format it into a dynamic object element located
-- in your seedobjects.xml file.
--
-- when used on any object the output will be
-- <DynamicObject>
-- <ObjectCreationParams>objects_template 2.0750000476837 0 13.704000473022 0 0 0 1 1 1</ObjectCreationParams>
-- </DynamicObject>
-- as it gathers all the rotations scales location information from the
-- in game object then this output gets clipped to your clipboard
-- simply open up your seedobjects.xml file and find your group
-- to simply CTRL+V (paste), this saves a bunch of time editing and adding
-- new content to your in game maps.
--
-- i added another feature that shows you how to add checks for special objects
-- i chose the simple_mob_spawner as the example.
-- in game /create simple_mob_spawner where you want your spawn to be
-- use the /info command on that spawner and click SeedClip
-- when you paste the information from the clipboard into your
-- seedobojects.xml file the output will be
-- <DynamicObject>
-- <ObjectCreationParams>simple_mob_spawner 3.3341825008392 0 20.994180679321 0 0 0 1 1 1</ObjectCreationParams>
-- <ObjectOverrides>
-- <StringVariable Name="spawnTemplate">template</StringVariable>
-- <DoubleVariable Name="spawnDelay">300</DoubleVariable>
-- <DoubleVariable Name="spawnCount">1</DoubleVariable>
-- <DoubleVariable Name="spawnRadius">0</DoubleVariable>
-- </ObjectOverrides>
-- </DynamicObject>
-- i used default settings so you simple just replace the template with your
-- template you want to spawn. Click save and off you go, easy peasy.
-- NOTES
-- This mod does not alter in any way how this menu works otherwise
-- if you need to take the parts I added look for CUSTOM in this file
function DoInfo(target)
curInfoObj = target
if not(curInfoObj) then
this:SystemMessage("Info Command: Invalid object")
return
end
local newWindow = DynamicWindow("InfoWindow","Object Info ("..curInfoObj.Id..")",440,500)
newWindow:AddLabel(20, 10, "[F3F781]Name: [-]"..(curInfoObj:GetName() or ""),600,0,18,"left",false)
if( IsPlayerCharacter(curInfoObj) ) then
local status = "Free"
if( not IsFreeAccount(curInfoObj) ) then status = "Paid" end
newWindow:AddLabel(200, 10, "[F3F781]Status:[-] " .. status,600,0,18,"left",false)
end
newWindow:AddLabel(20, 30, "[F3F781]Loc: [-]" ..tostring(curInfoObj:GetLoc()),600,0,18,"left",false)
newWindow:AddLabel(20, 50, "[F3F781]Template: [-]"..tostring(curInfoObj:GetCreationTemplateId()),600,0,18,"left",false)
newWindow:AddLabel(210, 50, "[F3F781]Hue: [-]"..tostring(curInfoObj:GetHue()),600,0,18,"left",false)
if(curInfoObj:IsPlayer()) then
newWindow:AddLabel(295, 50, "[F3F781]UserId: [-]"..tostring(curInfoObj:GetAttachedUserId()),600,0,18,"left",false)
else
newWindow:AddLabel(295, 50, "[F3F781]ClientId: [-]"..tostring(curInfoObj:GetIconId()),600,0,18,"left",false)
end
newWindow:AddLabel(20, 70, "[F3F781]Cloaked: [-]"..tostring(curInfoObj:IsCloaked()),600,0,18,"left",false)
newWindow:AddLabel(115, 70, "[F3F781]Frozen: [-]"..tostring(curInfoObj:IsMobileFrozen()),600,0,18,"left",false)
newWindow:AddLabel(200, 70, "[F3F781]Color: [-]"..tostring(curInfoObj:GetColor()),600,0,18,"left",false)
newWindow:AddButton(320, 10, "Refresh", "Refresh", 80, 23, "", "", false,"")
-----------------------------------------------------------------
-- CUSTOM UI BUTTON FOR CLIPPING THE DYNAMIC OBJECT
-----------------------------------------------------------------
newWindow:AddButton(320, 70, "SeedClip", "Seed Clip", 80, 23, "[FF7700]Seed Clip\n[CCCC00]This will create the xml element for the seed objects file. Simply goto the seed objects file, use CTRL+V or paste it in.", "", false,"")
local assetBundle = curInfoObj:GetAssetBundleName()
if(assetBundle ~= "") then
newWindow:AddLabel(295, 70, "[F3F781]Bundle: [-]".. assetBundle, 600,0,18,"left",false)
end
if curInfoObj:IsMobile() then
newWindow:AddLabel(20, 85, "[F3F781]Scale: [-]"..string.format("%4.2f",curInfoObj:GetScale().X),600,0,18,"left",false)
end
local behaviorState = ""
if(curTab == "Behaviors") then
behaviorState = "pressed"
end
local objvarState = ""
if(curTab == "ObjVars") then
objvarState = "pressed"
end
local statsState = ""
if(curTab == "Stats") then
statsState = "pressed"
end
if(curInfoObj:IsMobile()) then
newWindow:AddButton(20,100,"BehaviorsTab","Behaviors",126,23,"","",false,"",behaviorState)
newWindow:AddButton(146,100,"ObjVarsTab","Variables",126,23,"","",false,"",objvarState)
newWindow:AddButton(272,100,"StatsTab","Stats",126,23,"","",false,"",statsState)
else
newWindow:AddButton(20,100,"BehaviorsTab","Behaviors",190,23,"","",false,"",behaviorState)
newWindow:AddButton(210,100,"ObjVarsTab","Object Variables",190,23,"","",false,"",objvarState)
end
--newWindow:AddLabel(20, 100, "[F3F781]Behaviors:[-]",0,0,18,"left",true)
newWindow:AddImage(20,130,"DropHeaderBackground",380,310,"Sliced")
if(curTab == "Behaviors") then
local scrollWindow = ScrollWindow(25,135,355,225,25)
for i,behavior in pairs(curInfoObj:GetAllModules()) do
local scrollElement = ScrollElement()
if((i-1) % 2 == 1) then
scrollElement:AddImage(0,0,"Blank",320,25,"Sliced","242400")
end
scrollElement:AddLabel(5, 5, behavior,0,0,18,"left")
scrollElement:AddButton(210, 0, "", "Reload", 65, 23, "Reload Script", "reload "..behavior, false,"")
scrollElement:AddButton(275, 0, "Detach|"..behavior, "Detach", 65, 23, "Detach Script", "", false,"")
scrollWindow:Add(scrollElement)
end
newWindow:AddScrollWindow(scrollWindow)
newWindow:AddTextField(30, 375, 260, 20,"Attach", "")
newWindow:AddButton(305, 375, "Attach", "Attach", 80, 23, "", "", false,"")
newWindow:AddButton(40, 410, "SendMessage", "Send Message", 110, 23, "", "", false,"")
newWindow:AddButton(155, 410, "FireTimer", "Fire Timer", 110, 23, "", "", false,"")
newWindow:AddButton(270, 410, "Use", "Use", 110, 23, "", "", false,"")
elseif(curTab == "ObjVars") then
local array = GetObjVarsSorted(curInfoObj)
local scrollWindow = ScrollWindow(25,135,355,250,25)
for i,entry in pairs(array) do
local scrollElement = ScrollElement()
if((i-1) % 2 == 1) then
scrollElement:AddImage(0,0,"Blank",330,25,"Sliced","242400")
end
local varName = entry.name
if( varName:len() > 25 ) then
varName = varName:sub(1,22).."..."
end
scrollElement:AddLabel(5, 5, varName,0,0,18)
local varType = type(entry.value)
local valueLabel = nil
if( varType == "userdata" or varType == "table") then
valueLabel = "["..varType.."]"
else
valueLabel = tostring(entry.value)
end
scrollElement:AddLabel(200, 5, valueLabel,0,0,18)
local selState = ""
if(entry.name == selObjVar) then
selState = "pressed"
end
scrollElement:AddButton(320, 0, "Select|"..entry.name, "", 0, 22, "", "", false, "Selection",selState)
scrollWindow:Add(scrollElement)
end
newWindow:AddScrollWindow(scrollWindow)
newWindow:AddButton(60, 400, "AddObjVar", "Add", 100, 23, "", "", false,"")
local editState = selObjVar and "" or "disabled"
newWindow:AddButton(160, 400, "EditObjVar", "Edit", 100, 23, "", "", false,"",editState)
newWindow:AddButton(260, 400, "DelObjVar", "Delete", 100, 23, "", "", false,"",editState)
elseif(curTab == "Stats") then
local array = { "Health", "Mana", "Stamina", "Vitality", "Str", "Agi", "Int", "Con", "Wis", "Will", "Accuracy", "Evasion", "Attack", "Power", "Force", "Defense", "AttackSpeed"}
local scrollWindow = ScrollWindow(25,135,355,300,25)
for i,statName in pairs(array) do
local scrollElement = ScrollElement()
if((i-1) % 2 == 1) then
scrollElement:AddImage(0,0,"Blank",330,25,"Sliced","242400")
end
local varName = statName
if( varName:len() > 25 ) then
varName = varName:sub(1,22).."..."
end
scrollElement:AddLabel(5, 3, varName,0,0,18)
if(curInfoObj:IsRegeneratingStat(statName)) then
scrollElement:AddLabel(180, 3, tostring(math.round(curInfoObj:GetStatValue(statName),2)),0,0,18)
scrollElement:AddLabel(240, 3, tostring(math.round(curInfoObj:GetStatMaxValue(statName)),2),0,0,18)
scrollElement:AddLabel(290, 3, tostring(math.round(curInfoObj:GetStatRegenRate(statName)),2),0,0,18)
else
scrollElement:AddLabel(200, 3, tostring(math.round(curInfoObj:GetStatValue(statName)),2),0,0,18)
end
scrollWindow:Add(scrollElement)
end
newWindow:AddScrollWindow(scrollWindow)
end
this:OpenDynamicWindow(newWindow)
end
RegisterEventHandler(EventType.DynamicWindowResponse,"InfoWindow",
function (user,returnId,fieldData)
local commandInfo = GetCommandInfo("info")
if not(LuaCheckAccessLevel(this,commandInfo.AccessLevel)) then return end
if(returnId == "AddObjvar") then
this:SendClientMessage("EnterChat","/setobjvar "..curInfoObj.Id.." ")
elseif(returnId == "ToggleDebug") then
if(curInfoObj:HasObjVar("Debug")) then
curInfoObj:SetObjVar("Debug",true)
else
curInfoObj:DelObjVar("Debug")
end
elseif(returnId == "BehaviorsTab") then
curTab = "Behaviors"
DoInfo(curInfoObj)
elseif(returnId == "ObjVarsTab") then
curTab = "ObjVars"
DoInfo(curInfoObj)
elseif(returnId == "StatsTab") then
curTab = "Stats"
DoInfo(curInfoObj)
-----------------------------------------------------------------
-- CUSTOM CLICK RESPONSE FOR SEEDCLIP BUTTON
-----------------------------------------------------------------
elseif(returnId == "SeedClip") then
ClipToBoard()
DoInfo(curInfoObj)
elseif(returnId:match("Detach")) then
if(curInfoObj ~= nil) then
local behavior = returnId:sub(8)
curInfoObj:DelModule(behavior)
DelayRefresh()
end
elseif(returnId == "Attach") then
if(curInfoObj ~= nil and fieldData ~= nil and fieldData.Attach ~= nil and fieldData.Attach ~= "") then
curInfoObj:AddModule(fieldData.Attach)
DelayRefresh()
end
elseif(returnId:match("Select")) then
selObjVar = returnId:sub(8)
DoInfo(curInfoObj)
elseif(returnId == "EditObjVar") then
if(selObjVar ~= nil) then
InitObjVarEditWindow(curInfoObj,selObjVar)
end
elseif(returnId == "DelObjVar") then
if(selObjVar ~= nil) then
curInfoObj:DelObjVar(selObjVar)
DelayRefresh()
end
elseif(returnId == "AddObjVar") then
selObjVar = nil
objVarEditName = nil
InitObjVarEditWindow(curInfoObj)
elseif(returnId == "SendMessage" and fieldData ~= nil and fieldData.Attach ~= nil and fieldData.Attach ~= "") then
local fieldComps = StringSplit(fieldData.Attach," ")
if(fieldComps ~= nil and #fieldComps > 0 and curInfoObj:IsValid()) then
local msgName = fieldComps[1]
curInfoObj:SendMessage(msgName,ParseMessageArgs(fieldComps))
this:SystemMessage("Sent message "..msgName.." to "..curInfoObj:GetName())
end
elseif(returnId == "FireTimer" and fieldData ~= nil and fieldData.Attach ~= nil and fieldData.Attach ~= "") then
local fieldComps = StringSplit(fieldData.Attach," ")
if(fieldComps ~= nil and #fieldComps > 0 and curInfoObj:IsValid()) then
local timerName = fieldComps[1]
if(timerName ~= nil and timerName ~= "") then
curInfoObj:FireTimer(timerName,ParseMessageArgs(fieldComps))
this:SystemMessage("Fired timer "..timerName.." on "..curInfoObj:GetName())
end
end
elseif(returnId == "Use") then
if(fieldData ~= nil and fieldData.Attach ~= nil and fieldData.Attach ~= "") then
local fieldComps = StringSplit(fieldData.Attach," ")
if(fieldComps ~= nil and #fieldComps > 0 and curInfoObj:IsValid()) then
local useType = fieldComps[1]
curInfoObj:SendMessage("UseObject",this,useType)
this:SystemMessage("Fired UseObject type:"..useType.." on "..curInfoObj:GetName())
end
else
curInfoObj:SendMessage("UseObject",this)
this:SystemMessage("Fired UseObject on "..curInfoObj:GetName())
end
elseif(returnId == "Refresh") then
DoInfo(curInfoObj)
else
curInfoObj = nil
selObjVar = nil
end
end)
-----------------------------------------------------------------
-- CUSTOM FUNCTIONS FOR THE CLIP BUTTON
-----------------------------------------------------------------
function ClipToBoard()
local clipString = ""
local finalString = ""
local template = curInfoObj:GetCreationTemplateId()
local location = curInfoObj:GetLoc()
local rotation = curInfoObj:GetRotation()
local scale = curInfoObj:GetScale()
local dynamicObjectElement = xml.new("DynamicObject")
local creationParams = template .. " " ..
location.X .. " " ..
location.Y .. " " ..
location.Z .. " " ..
rotation.X .. " " ..
rotation.Y .. " " ..
rotation.Z .. " " ..
scale.X .. " " ..
scale.Y .. " " ..
scale.Z
-- add the objectcreationparams element and element data
dynamicObjectElement:append("ObjectCreationParams")[1] = creationParams
if(template == "simple_mob_spawner") then
local objVarOverridesElement = xml.new("ObjVarOverrides")
local spawnTemplateElement = xml.new("StringVariable")
local spawnDelayElement = xml.new("DoubleVariable")
local spawnCountElement = xml.new("DoubleVariable")
local spawnRadiusElement = xml.new("DoubleVariable")
-- spawnTemplate
spawnTemplateElement[1] = "template"
spawnTemplateElement["Name"] = "spawnTemplate"
objVarOverridesElement:append(spawnTemplateElement)
-- spawnDelay
spawnDelayElement[1] = 300 -- default 5 minutes
spawnDelayElement["Name"] = "spawnDelay"
objVarOverridesElement:append(spawnDelayElement)
--spawnCount
spawnCountElement[1] = 1 -- default spawn of 1
spawnCountElement["Name"] = "spawnCount"
objVarOverridesElement:append(spawnCountElement)
--spawnRadius
spawnRadiusElement[1] = 0 -- default to spawn at spawner location
spawnRadiusElement["Name"] = "spawnRadius"
objVarOverridesElement:append(spawnRadiusElement)
dynamicObjectElement:append(objVarOverridesElement)
end
clipString = string.gsub(tostring(dynamicObjectElement),""","\"")
finalString = AddIndentX2(clipString)
io.popen('clip','w'):write(finalString):close()
end
function AddIndentX2(str)
local result = {}
local finalResult = ""
for line in str:gmatch '[^\n]+' do
table.insert(result, line)
end
for k,v in pairs(result) do
finalResult = finalResult .. "\t\t"..v.."\n"
end
return finalResult
end