SeedClipMod

From Legends of Aria Admin and Modding Wiki
Jump to: navigation, search

Preview Video

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 Output 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),"&quot;","\"")
    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

scriptcommands option

  • below is another option as you can copy paste this to your scriptcommands.lua override
  • type in /custom in game in the text field type clip hit update and drag an icon out to your hotbar.
  • and enjoy
function GetClipTarget()
	this:SystemMessage("target a object you want to clip to the clip board")
	this:RequestClientTargetGameObj(this, "targetToClip")
end

function HandleClipTarget(target,user)
	if(target==nil) then return end

	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),"&quot;","\"")
    finalString = AddIndentX2(clipString)
	io.popen('clip','w'):write(finalString):close()
	user:SystemMessage("Object Cliped CTRL+V To Paste")
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

RegisterEventHandler(EventType.ClientTargetGameObjResponse, "targetToClip", HandleClipTarget)

RegisterCommand { Command="clip",Category="GizmosTools",AccessLevel=AccessLevel.God,Func=GetClipTarget,Usage="<clientids>", Desc="Copies the objects data and formats it then pastes it to the clip board. This allows you to paste in your <dynamicobject> element block in your seedobjects.xml file." }