-- by modelleicher
-- June 2016
-- www.schwabenmodding.de
-- facebook.de/modelleicher
-- ideas and motivation: Maxter

-- Version 1.1, still Fs15, few minor bug fixes

winch = {};

function winch.prerequisitesPresent(specializations)
    return true;
end;

function winch:load(xmlFile)
	--self.searchTrigger = winch.searchTrigger;
	self.onOff = winch.onOff;
	self.clientServerSetWinching = winch.clientServerSetWinching;
	self.clientServerDetachTree = winch.clientServerDetachTree;
	self.clientServerAttachTree = winch.clientServerAttachTree;
	self.createFinderShape = winch.createFinderShape;
	self.clientServerFindTree = winch.clientServerFindTree;
	
	self.w = {};
	self.w.workingRadius = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.winch#workingRadius"), 50);
	self.w.isOn = false;
	
	self.w.attacherNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.winch#attacherNode"));
	self.w.attacherCompIndex = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.winch#attacherComponent"), 1);
	
	setMass(self.components[self.w.attacherCompIndex].node, 0.8);
	
	self.w.attacherHelperNode = createTransformGroup("attacherHelperNode");
	link(self.w.attacherNode, self.w.attacherHelperNode);
	setRotation(self.w.attacherHelperNode, 0, 0, 0);

	self.w.rope = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.winch#rope"));
	setVisibility(self.w.rope, false);
	
	self.w.speed = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.winch#speed"), 1)*0.0005;
	
	
	--self.w.loop = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.winch#loop"));
	--setVisibility(self.w.loop, false);
	--self.w.loopTarget = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.winch#loopTarget"));
	
	self.w.massTimer = false;
	self.w.massTimerMs = 0;
	
	self.w.winching = false;
end;

function winch:delete()
end;
function winch:mouseEvent(posX, posY, isDown, isUp, button)
end;
function winch:keyEvent(unicode, sym, modifier, isDown)
end;
function winch:onOff(state, noEventSend)
	if state ~= self.w.isOn then
		self.w.isOn = state;
		winchOnOffEvent.sendEvent(self, state, noEventSend);
	end;
end;
function winch:clientServerSetWinching(state, noEventSend)
	if state ~= self.w.winching then
		self.w.winching = state;
		--print("SetWinching called");
		winchSetWinchingEvent.sendEvent(self, state, noEventSend);
	end;
end;
function winch:clientServerDetachTree(noEventSend)
	--print("clientServerDetachTree_called")
	if self.isServer then
		setMass(self.w.localAttachedSplit, self.w.splitBackupMass);	
		self.w.splitBackupMass = nil;
		removeJoint(self.w.serverAttachedSplit);
		--print("clientServerDetachTree_called_isServer")
	end;
	self.w.serverAttachedSplit = nil;	
	self.w.localAttachedSplit = nil;
	self.w.localSplitAttacherRef = nil;
	self.w.foundLocalSplit = nil;
	self.w.wUpdated = true;
	self.w.winching = false;
	setVisibility(self.w.rope, false);	
	--setVisibility(self.w.loop, false);
	--unlink(self.w.loop);
	--link(getParent(self.w.rope), self.w.loop);
	winchDetachTreeEvent.sendEvent(self, noEventSend);
end;
--
function winch:createFinderShape(centerNode)
	local planePoint = createTransformGroup("planePoint");
	link(centerNode, planePoint);
	setRotation(planePoint, math.rad(0), math.rad(0), math.rad(180));
	setTranslation(planePoint, 0, 0.5, -0.5);
	
	local dir1 = createTransformGroup("dir1");
	local dir2 = createTransformGroup("dir2");
	link(planePoint, dir1);
	link(planePoint, dir2);
	setTranslation(dir1, 1, 0, 0);
	setTranslation(dir2, 0, 1, 0);
	--print("createFinderShape_created")
	return planePoint, dir1, dir2;
end;

function winch:clientServerFindTree(tX, tY, tZ, rX, rY, rZ, isLocal, noEventSend, lA, lB, lC, scaleY, scaleZ)
	--print("ClientServer_findTree called");
	self.w.wUpdated = true;
	-- find the tree for each client/server according to center point pos/rot
	if not isLocal then -- only find tree for others, not for oneself since the current player already found the tree
		--print("clientServer_findTree_notLocal");
		local center = createTransformGroup("local_center");
		link(getRootNode(), center);
		setTranslation(center, tX, tY, tZ);
		setRotation(center, rX, rY, rZ);
		local planePoint, dir1, dir2 = self:createFinderShape(center);
		local pX, pY, pZ = getWorldTranslation(planePoint);
		local dir1X, dir1Y, dir1Z = getWorldTranslation(dir1);
		local dir2X, dir2Y, dir2Z = getWorldTranslation(dir2);
		local nx, ny, nz, yx, yy, yz = dir1X-pX, dir1Y-pY, dir1Z-pZ, dir2X-pX, dir2Y-pY, dir2Z-pZ;	
		local shape, minY, maxY, minZ, maxZ = findSplitShape(pX,pY,pZ, nx, ny, nz, yx, yy, yz, 1, 1);	
		if shape == nil or shape == 0 then
			--print("ERROR: Winch.lua - No shape found at given coordinates!");
		else
			--print("self.w.foundLocalSplit -> found split "..tostring(minY));
			self.w.foundLocalSplit = shape;
			self.w.foundLocalSplitSizes = {minY, maxY, minZ, maxZ};
		
			-- loop placement (and attacher placement relative to that) data
			local lA, lB, lC = localToWorld(planePoint, 0, (minY+maxY)*0.5, (minZ+maxZ)*0.5)
			local scaleY = maxY-minY;
			local scaleZ = maxZ-minZ;
			self:clientServerAttachTree(tX, tY, tZ, rX, rY, rZ, lA, lB, lC, scaleY, scaleZ);
			
		end;
		delete(center);
	else 
		--print("clientServer_findTree_isLocal");
		self:clientServerAttachTree(tX, tY, tZ, rX, rY, rZ, lA, lB, lC, scaleY, scaleZ);
		winchAttachTreeEvent.sendEvent(self, tX, tY, tZ, rX, rY, rZ, noEventSend);
	end;
end;

function winch:clientServerAttachTree(tX, tY, tZ, rX, rY, rZ, lA, lB, lC, scaleY, scaleZ)
	--print("clientServer_attachTree_called")
	
	local split = Utils.getNoNil(self.w.foundLocalSplit, self.w.currentLocalSplit);
	--print("attach_tree_split: "..tostring(split));
	self.w.localSplitAttacherRef = createTransformGroup("attacherReference"); -- create attacher reference 
	link(split, self.w.localSplitAttacherRef);		
	local lx, ly, lz = worldToLocal(self.w.localSplitAttacherRef, tX, tY, tZ);    -- position of where the player attaches the rope
	setTranslation(self.w.localSplitAttacherRef, lx, ly, lz);
	self.w.localAttachedSplit = split;
	
	-- the loop..
	-- now, there is really no 100% way of doing this
	-- as the giants trees have to many variables in size, position / relative position of 0 0 0 to the tree
	-- the safest bet are the spruce trees.. So those will be easy. Thats why those are handled seperately
	
	-- spruce tree loop to trunk adding stuff here:
	--self.w.currentSplitType = getSplitType(split); 
	--if self.w.currentSplitType == 2 then -- spruce
		-- add loop to trunk
	--	unlink(self.w.loop);
	--	link(split, self.w.loop);
		-- locate loop in Y/Z center of trunk
	--	local lX, lY, lZ = worldToLocal(getParent(self.w.loop), lA, lB, lC);
	--	setTranslation(self.w.loop, lX, lY, lZ);
		-- set direction of loop towards big end of trunk
	--	local q, w, e = getWorldTranslation(self.w.loop);
	--	local r, t, z = getWorldTranslation(split);
	--	local dirX, dirY, dirZ = worldDirectionToLocal(getParent(self.w.loop), q-r, w-t, e-z);
	--	setDirection(self.w.loop, dirX, dirY, dirZ, 0, -1, 0);	
		-- in case the tree gets attached at the small end of the trunk...
		-- find out if the winch is in opposide direction, then rotate loop 180°
		-- to do!
		
	--	setScale(self.w.loop, scaleY*5.5, scaleY*5.5, scaleZ*5.5);
	--	setVisibility(self.w.loop, true);
	--end;

	
	
	-- now the rotation stuff
	--local r1, r2, r3 = getRotation(split);
	--print(tostring(r1).."-"..tostring(r2).."-"..tostring(r3));
	--local r4, r5, r6 = getRotation(self.w.loop);
	--setRotation(self.w.loop, r4, r5, -r1);
	
	
	-- set rotation of the loop (the fun part this is)
	--local lrX, lrY, lrZ = getWorldRotation(self.w.loop);
	--lrX, lrY , lrZ = worldToLocal(split, lrX, lrY, math.rad(0));
	--setRotation(self.w.loop, lrX, lrY, lrZ);
	-- set direction of loop to point to tree 0 0 0 point (not really accurate but most accurate possible to my knowledge so far)

	

	-- 
	
	if self.isServer then -- only the server can actually attach the tree
		
		-- lower the mass of the tree while it is attached to stabilize the joint
		self.w.splitBackupMass = getMass(split);
		setMass(split, self.w.splitBackupMass*0.5);
		
		-- lower mass of rope component during attaching to stop tree from jumping
		setMass(self.components[self.w.attacherCompIndex].node, 0.01);
		self.w.massTimer = true;
		
		local constr = JointConstructor:new();
		constr:setActors(self.components[self.w.attacherCompIndex].node, split);
		
		local x, y, z = getWorldTranslation(self.w.attacherNode);
		local a, b, c = getWorldTranslation(self.w.localSplitAttacherRef);
		constr:setJointTransforms(self.w.attacherNode, self.w.localSplitAttacherRef);
		-- get the current distance and set the translation limit to it
		local distance = Utils.vector3Length(x-a, y-b, z-c);
		transRadius = distance+0.1
		local ten = 0.05
		constr:setTranslationLimit(0, true, -ten, ten);
		constr:setTranslationLimit(1, true, -ten, ten);
		constr:setTranslationLimit(2, true, -transRadius, transRadius);

		constr:setTranslationLimitSpring(0, 0, 0, 0, 0, 0);
		
		constr:setEnableCollision(false);
		self.w.serverAttachedSplit = constr:finalize();	
		setJointRotationLimit(self.w.serverAttachedSplit, 0, false, 0, 0); -- set rot limit false since the tree is able to rotate on the winch
		self.w.curLimit = transRadius+0.01;
		

		--print("done attaching");
	end;	
	self.w.foundLocalSplit = nil;
end;


function winch:update(dt)	
	if self:getIsActiveForInput() then	
		if InputBinding.hasEvent(InputBinding.WINCH_ME_ACTIVATE) then
			if self.w.localAttachedSplit == nil then
				self:onOff(not self.w.isOn);
			end;
		end;
	end;
	
	-- the new stuff... 29.06.2016
	if self.w.isOn then
		-- server only
		renderText(0.001, 0.0016, 0.02, "Winch active!");
		if self.w.serverAttachedSplit ~= nil then
			--renderText(0.001, 0.5, 0.02, "Debug: tree orig. mass = "..tostring(self.w.splitBackupMass))
			--renderText(0.001, 0.45, 0.02, "Debug: tree new mass = "..tostring(getMass(self.w.localAttachedSplit)));
			if self.w.winching then -- 0.0005
				self.w.curLimit = math.max(0.1, self.w.curLimit - (self.w.speed*dt));
				setJointTranslationLimit(self.w.serverAttachedSplit, 2, true, -self.w.curLimit, self.w.curLimit)
			end;
			--renderText(0.001, 0.7, 0.02, "Debug: self.w.serverAttachedSplit ~= nil")
		end;
		
		-- all
		if self.w.localAttachedSplit ~= nil then 
			-- rope animation
			--renderText(0.001, 0.67, 0.02, "Current SplitType: "..tostring(self.w.currentSplitType));
			local x, y, z = getWorldTranslation(self.w.localSplitAttacherRef);
			local a, b, c = getWorldTranslation(self.w.rope);
			local dirX, dirY, dirZ = worldDirectionToLocal(getParent(self.w.attacherNode), x-a, y-b, z-c);
			local upx, upy, upz = 0,1,0;
			setDirection(self.w.rope, dirX, dirY, dirZ, upx, upy, upz);
			local distance = Utils.vector3Length(a-x, b-y, c-z);
			setScale(self.w.rope, 1, 1, distance);
			setVisibility(self.w.rope, true);
		end;
		
		if self.w.massTimer then
			self.w.massTimerMs = self.w.massTimerMs + dt;
			if self.w.massTimerMs > 1000 then
				self.w.massTimer = false;
				self.w.massTimerMs = 0;
				-- set rope component mass back to normal
				setMass(self.components[self.w.attacherCompIndex].node, 0.8);
				--print("Mass Timer reset")
			end;
		end;
		
		-- individual player
		if g_currentMission.controlPlayer and g_currentMission.player ~= nil then
			-- get the distance from the player to the winch to check if the player is within the length of the rope
			local x,y,z = getWorldTranslation(g_currentMission.player.rootNode);
			local a,b,c = getWorldTranslation(self.rootNode)
			local distance = Utils.vector3Length(x-a, y-b, z-c);
			if distance < self.w.workingRadius then -- player is in attaching range
				renderText(0.08, 0.0016, 0.02, "distance to winch: "..tostring(math.floor(distance)).."m");
				if self.firstTimeActive == nil then -- add the search plane to player
					self.w.searchNodes = {};
					self.w.searchNodes.center = createTransformGroup("centerNode");
					link(g_currentMission.player.cameraId, self.w.searchNodes.center);
					setTranslation(self.w.searchNodes.center, 0, 0, -1);
					local planePoint, dir1, dir2 = self:createFinderShape(self.w.searchNodes.center);
					self.w.searchNodes.planePoint = planePoint;
					self.w.searchNodes.dir1 = dir1;
					self.w.searchNodes.dir2 = dir2;
					self.firstTimeActive = true;
				end;
				-- draw center point debug point
				local dX, dY, dZ = getWorldTranslation(self.w.searchNodes.center);
				drawDebugPoint(dX,dY,dZ,1,0.5,1,1);
				
				-- find trees...
				local pX, pY, pZ = getWorldTranslation(self.w.searchNodes.planePoint);
				local dir1X, dir1Y, dir1Z = getWorldTranslation(self.w.searchNodes.dir1);
				local dir2X, dir2Y, dir2Z = getWorldTranslation(self.w.searchNodes.dir2);

				local nx, ny, nz, yx, yy, yz = dir1X-pX, dir1Y-pY, dir1Z-pZ, dir2X-pX, dir2Y-pY, dir2Z-pZ;
				
				local shape, minY, maxY, minZ, maxZ = findSplitShape(pX,pY,pZ, nx, ny, nz, yx, yy, yz, 1, 1);
				if shape ~= nil and shape ~= 0 then -- found split shape
					self.w.currentLocalSplit = shape;
					self.w.currentLocalSplitSizes = {minY, maxY, minZ, maxZ};
					
					if self.w.localAttachedSplit == nil then
						renderText(0.3, 0.0016, 0.02, "Tree in Range. Press N to attach");
						if self.w.wUpdated == nil and InputBinding.hasEvent(InputBinding.WINCH_ME_ATTACH) then -- attach log
							--print("WINCH_ATTACH_INPUT_CALL")
							local tX, tY, tZ = getWorldTranslation(self.w.searchNodes.center);
							local rX, rY, rZ = getWorldRotation(self.w.searchNodes.center);
							
							-- loop placement (and attacher placement relative to that) data
							local lA, lB, lC = localToWorld(self.w.searchNodes.planePoint, 0, (minY+maxY)*0.5, (minZ+maxZ)*0.5)
							local scaleY = maxY-minY;
							local scaleZ = maxZ-minZ;
							
							self:clientServerFindTree(tX, tY, tZ, rX, rY, rZ, true, nil, lA, lB, lC, scaleY, scaleZ);
							--print("WINCH_ATTACH_INPUT_CALL_control")
						end;
					end;
				else	
					self.w.currentLocalSplit = nil;
				end;
				-- check if winching is enabled
				if self.w.localAttachedSplit ~= nil then
					renderText(0.3, 0.0016, 0.02, "Tree attached. Press M to detach, K to winch the tree.");
					if InputBinding.isPressed(InputBinding.WINCH_ME_WINCHING) then
						self:clientServerSetWinching(true);
					else
						self:clientServerSetWinching(false);
					end;
					-- check if detaching is enabled, detachTree
					if self.w.wUpdated == nil and InputBinding.hasEvent(InputBinding.WINCH_ME_DETACH) then
						self:clientServerDetachTree();
						--print("WINCH_DETACH_INPUT_CALL");
					end;	
				end;
			end;
		end;
		self.w.wUpdated = nil;
    end;
end;	


function winch:draw()
	if self:getIsActiveForInput() then
		g_currentMission:addHelpButtonText(g_i18n:getText("WINCH_ME_ACTIVATE"), InputBinding.WINCH_ME_ACTIVATE);
	end;
end;
				
				--if minY ~= nil then
				--	local a,b,c = localToWorld(self.w.shapeMeasureNode, 0, (minY+maxY)*0.5, (minZ+maxZ)*0.5);
	           --     --x, y, z = worldToLocal(getParent(self.ringSelector), a,b,c);
				--	drawDebugLine(a, b, c, 1, 0, 0, a+1, b, c, 1, 0, 0);
				--	drawDebugLine(a, b, c, 0, 1, 0, a, b+1, c, 0, 1, 0);
				--	drawDebugLine(a, b, c, 0, 0, 1, a, b, c+1, 0, 0, 1);
				--end;
				
-- OnOff Event
winchOnOffEvent = {};
winchOnOffEvent_mt = Class(winchOnOffEvent, Event);

InitEventClass(winchOnOffEvent, "winchOnOffEvent");

function winchOnOffEvent:emptyNew()
	local self = Event:new(winchOnOffEvent_mt);
    return self;
end;

function winchOnOffEvent:new(object, state)
	local self = winchOnOffEvent:emptyNew();
	self.object = object;
	self.state = state;
	return self;
end;

function winchOnOffEvent:readStream(streamId, connection)
	local id = streamReadInt32(streamId);
	self.object = networkGetObject(id);
	self.state = streamReadBool(streamId);
    self:run(connection);
end;

function winchOnOffEvent:writeStream(streamId, connection)
	streamWriteInt32(streamId, networkGetObjectId(self.object));
	streamWriteBool(streamId, self.state);
end;

function winchOnOffEvent:run(connection)
	self.object:onOff(self.state, true);
	if not connection:getIsServer() then
		g_server:broadcastEvent(winchOnOffEvent:new(self.object, self.state), nil, connection, self.object);
	end;
end;

function winchOnOffEvent.sendEvent(object, state, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(winchOnOffEvent:new(object, state), nil, nil, object);
		else
			g_client:getServerConnection():sendEvent(winchOnOffEvent:new(object, state));
		end;
	end;
end;
				
				
-- setWinching Event
winchSetWinchingEvent = {};
winchSetWinchingEvent_mt = Class(winchSetWinchingEvent, Event);

InitEventClass(winchSetWinchingEvent, "winchSetWinchingEvent");

function winchSetWinchingEvent:emptyNew()
	local self = Event:new(winchSetWinchingEvent_mt);
    return self;
end;

function winchSetWinchingEvent:new(object, state)
	local self = winchSetWinchingEvent:emptyNew();
	self.object = object;
	self.state = state;
	return self;
end;

function winchSetWinchingEvent:readStream(streamId, connection)
	local id = streamReadInt32(streamId);
	self.object = networkGetObject(id);
	self.state = streamReadBool(streamId);
    self:run(connection);
end;

function winchSetWinchingEvent:writeStream(streamId, connection)
	streamWriteInt32(streamId, networkGetObjectId(self.object));
	streamWriteBool(streamId, self.state);
end;

function winchSetWinchingEvent:run(connection)
	self.object:clientServerSetWinching(self.state, true);
	if not connection:getIsServer() then
		g_server:broadcastEvent(winchSetWinchingEvent:new(self.object, self.state), nil, connection, self.object);
	end;
end;

function winchSetWinchingEvent.sendEvent(object, state, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(winchSetWinchingEvent:new(object, state), nil, nil, object);
		else
			g_client:getServerConnection():sendEvent(winchSetWinchingEvent:new(object, state));
		end;
	end;
end;				
				


winchAttachTreeEvent = {};
winchAttachTreeEvent_mt = Class(winchAttachTreeEvent, Event);

InitEventClass(winchAttachTreeEvent, "winchAttachTreeEvent");

function winchAttachTreeEvent:emptyNew()
	local self = Event:new(winchAttachTreeEvent_mt);
    return self;
end;

function winchAttachTreeEvent:new(object, tX, tY, tZ, rX, rY, rZ)
	local self = winchAttachTreeEvent:emptyNew();
	self.object = object;
	self.tX = tX;
	self.tY = tY;
	self.tZ = tZ;
	self.rX = rX;
	self.rY = rY;
	self.rZ = rZ;
	return self;
end;

function winchAttachTreeEvent:readStream(streamId, connection)
	local id = streamReadInt32(streamId);
	self.object = networkGetObject(id);
	self.tX = streamReadFloat32(streamId);
	self.tY = streamReadFloat32(streamId);
	self.tZ = streamReadFloat32(streamId);
	self.rX = streamReadFloat32(streamId);
	self.rY = streamReadFloat32(streamId);
	self.rZ = streamReadFloat32(streamId);	
    self:run(connection);
end;

function winchAttachTreeEvent:writeStream(streamId, connection)
	streamWriteInt32(streamId, networkGetObjectId(self.object));
	streamWriteFloat32(streamId, self.tX);
	streamWriteFloat32(streamId, self.tY);
	streamWriteFloat32(streamId, self.tZ);
	streamWriteFloat32(streamId, self.rX);
	streamWriteFloat32(streamId, self.rY);	
	streamWriteFloat32(streamId, self.rZ);
end;

function winchAttachTreeEvent:run(connection)
	--print("EVENT_winchAttachTreeEvent_RUN");
	self.object:clientServerFindTree(self.tX, self.tY, self.tZ, self.rX, self.rY, self.rZ, false, true);
	if not connection:getIsServer() then
		g_server:broadcastEvent(winchAttachTreeEvent:new(self.object, self.tX, self.tY, self.tZ, self.rX, self.rY, self.rZ), nil, connection, self.object);
	end;
end;

function winchAttachTreeEvent.sendEvent(object, tX, tY, tZ, rX, rY, rZ, noEventSend)
	--print("EVENT_winchAttachTreeEvent_sendEvent");
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			--print("EVENT_winchAttachTreeEvent_sendEvent_g_server");
			g_server:broadcastEvent(winchAttachTreeEvent:new(object, tX, tY, tZ, rX, rY, rZ ), nil, nil, object);
		else
			--print("EVENT_winchAttachTreeEvent_sendEvent_g_client");
			g_client:getServerConnection():sendEvent(winchAttachTreeEvent:new(object, tX, tY, tZ, rX, rY, rZ));
		end;
	end;
end;

				
winchDetachTreeEvent = {};
winchDetachTreeEvent_mt = Class(winchDetachTreeEvent, Event);

InitEventClass(winchDetachTreeEvent, "winchDetachTreeEvent");

function winchDetachTreeEvent:emptyNew()
	local self = Event:new(winchDetachTreeEvent_mt);
    return self;
end;

function winchDetachTreeEvent:new(object)
	local self = winchDetachTreeEvent:emptyNew();
	self.object = object;
	return self;
end;

function winchDetachTreeEvent:readStream(streamId, connection)
	local id = streamReadInt32(streamId);
	self.object = networkGetObject(id);
    self:run(connection);
end;

function winchDetachTreeEvent:writeStream(streamId, connection)
	streamWriteInt32(streamId, networkGetObjectId(self.object));
end;

function winchDetachTreeEvent:run(connection)
	--print("EVENT_winchDetachTreeEvent_run");
	self.object:clientServerDetachTree(true);
	if not connection:getIsServer() then
		g_server:broadcastEvent(winchDetachTreeEvent:new(self.object), nil, connection, self.object);
	end;
end;
	
function winchDetachTreeEvent.sendEvent(object, noEventSend)
	--print("EVENT_winchDetachTreeEvent_sendEvent");
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			--print("EVENT_winchDetachTreeEvent_sendEvent_g_server");
			g_server:broadcastEvent(winchDetachTreeEvent:new(object), nil, nil, object);
		else
			--print("EVENT_winchDetachTreeEvent_sendEvent_g_client");
			g_client:getServerConnection():sendEvent(winchDetachTreeEvent:new(object));
		end;
	end;
end;	
				