function EntityGetVariable(entity, name, type)
	value = nil
	variable_storages = EntityGetComponentIncludingDisabled(entity, "VariableStorageComponent")
	if(variable_storages ~= nil)then
		for k, v in pairs(variable_storages)do
			name_out = ComponentGetValue2(v, "name")
			if(name_out == name)then
				value = ComponentGetValue2(v, "value_"..type)
			end
		end
	end
	return value
end

function EntitySetVariable(entity, name, type, value)
	variable_storages = EntityGetComponentIncludingDisabled(entity, "VariableStorageComponent")
	has_been_set = false
	if(variable_storages ~= nil)then
		for k, v in pairs(variable_storages)do
			name_out = ComponentGetValue2(v, "name")
			if(name_out == name)then
				ComponentSetValue2(v, "value_"..type, value)
				has_been_set = true
			end
		end
	end
	if(has_been_set == false)then
		comp = {}
		comp.name = name
		comp["value_"..type] = value
		EntityAddComponent2(entity, "VariableStorageComponent", comp)
	end
end


function EntityHasFlag(entity, name)
	value = false
	variable_storages = EntityGetComponentIncludingDisabled(entity, "VariableStorageComponent")
	if(variable_storages ~= nil)then
		for k, v in ipairs(variable_storages)do
			name_out = ComponentGetValue2(v, "name")
			if(name_out == name)then
				value = ComponentGetValue2(v, "value_bool")
			end
		end
	end
	return value
end

function EntityHasChildWithFlag(entity, name)
    value = false
    children = EntityGetAllChildren(entity)
    if(children ~= nil)then
        for k, v in ipairs(children)do
            if(EntityHasFlag(v, name))then
                value = true
            end
        end
    end
    return value
end


function EntityAddFlag(entity, name)
	variable_storages = EntityGetComponentIncludingDisabled(entity, "VariableStorageComponent")
	has_been_set = false
	if(variable_storages ~= nil)then
		for k, v in ipairs(variable_storages)do
			name_out = ComponentGetValue2(v, "name")
			if(name_out == name)then
				ComponentSetValue2(v, "value_bool", true)
				has_been_set = true
			end
		end
	end
	if(has_been_set == false)then
		comp = {}
		comp.name = name
		comp["value_bool"] = true
		EntityAddComponent2(entity, "VariableStorageComponent", comp)
	end
end

function EntityRemoveFlag(entity, name)
	variable_storages = EntityGetComponentIncludingDisabled(entity, "VariableStorageComponent")
	if(variable_storages ~= nil)then
		for k, v in ipairs(variable_storages)do
			name_out = ComponentGetValue2(v, "name")
			if(name_out == name)then
				EntityRemoveComponent(entity, v)
			end
		end
	end
end

function EntityAdjustVariable( entity, name, type, default, callback )
    local new_value = callback( EntityGetVariable( entity, name, type ) or default );
    EntitySetVariable( entity, name, type, new_value );
    return new_value;
end

function ComponentAdjustValue( component, member, callback )
    local new_value = callback( ComponentGetValue2( component, member ) );
    ComponentSetValue2( component, member, new_value );
    return new_value;
end

function ComponentSetValues( component, member_value_table )
    for member,new_value in pairs(member_value_table) do
        ComponentSetValue2( component, member, new_value );
    end
end

function ComponentAdjustValues( component, member_callback_table )
    for member,callback in pairs( member_callback_table ) do
        ComponentSetValue2( component, member, callback( ComponentGetValue2( component, member ) ) );
    end
end

function ComponentObjectSetValues( component, object, member_value_table )
    for member,new_value in pairs(member_value_table) do
        ComponentObjectSetValue2( component, object, member, new_value );
    end
end

function ComponentObjectAdjustValues( component, object, member_callback_table )
    for member,callback in pairs(member_callback_table) do
        ComponentObjectSetValue2( component, object, member, callback( ComponentObjectGetValue2( component, object, member ) ) );
    end
end

function ComponentSetValues( component, member_value_table )
    for member,new_value in pairs(member_value_table) do
        ComponentSetValue2( component, member, new_value );
    end
end

function ComponentAdjustMetaCustoms( component, member_callback_table )
    for member,callback in pairs(member_callback_table) do
        local current_value = ComponentGetValue2( component, member );
        local new_value = callback( current_value );
        ComponentSetValue2( component, member, new_value );
    end
end

function EntityIterateComponentsByType( entity, component_type_name, callback )
    local matched_components = {};
    local components = EntityGetAllComponents( entity ) or {};
    for _,component in pairs(components) do
        if ComponentGetTypeName( component ) == component_type_name then
            table.insert( matched_components, component );
        end
    end
    if callback ~= nil then
        for _,component in pairs(matched_components) do
            callback( component );
        end
    end
    return matched_components;
end

function getCurrentlyEquippedWandId(shooter)
	local i2c_id = EntityGetFirstComponentIncludingDisabled(shooter, "Inventory2Component")
	local wand_id = ComponentGetValue2( i2c_id, "mActiveItem" )
	
	if(EntityHasTag(wand_id, "wand")) then
		return wand_id
	else
		return nil
	end
end

function get_projectile_root_shooter( entity )
    local root_shooter = entity;
    local projectile = EntityGetFirstComponent( entity, "ProjectileComponent" );
    if projectile ~= nil then
        local shooter = ComponentGetValue2( projectile, "mWhoShot" );
        while shooter ~= nil and shooter ~= 0 do
            root_shooter = shooter;
            local shooter_projectile = EntityGetFirstComponent( shooter, "ProjectileComponent" );
            if shooter_projectile == nil then
                break;
            end
            shooter = ComponentGetValue2( shooter_projectile, "mWhoShot" );
        end
    end
    return root_shooter;
end

function make_projectile_not_damage_shooter( entity, force_shooter )
    local projectile = EntityGetFirstComponent( entity, "ProjectileComponent" );
    if projectile ~= nil then
        ComponentSetValue2( projectile, "explosion_dont_damage_shooter", true );
        ComponentSetValue2( projectile, "friendly_fire", false );
        local shooter = force_shooter or get_projectile_root_shooter( entity );
        if shooter ~= nil and shooter ~= 0 then
            ComponentObjectSetValue( projectile, "config_explosion", "dont_damage_this", tostring( shooter ) );
            EntityIterateComponentsByType( entity, "AreaDamageComponent", function(component)
                if EntityHasTag( shooter, "player_unit" ) then
                    ComponentSetValue2( component, "entities_with_tag", "enemy" );
                else
                    ComponentSetValue2( component, "entities_with_tag", "player_unit" );
                end
            end );

            local lightning = EntityGetFirstComponent( entity, "LightningComponent" );
            if lightning ~= nil then
                ComponentObjectSetValue( lightning, "config_explosion", "dont_damage_this", tostring( shooter ) );
            end
        end
    end
end

function EntityHasFlag(entity, name)
	value = false
	variable_storages = EntityGetComponentIncludingDisabled(entity, "VariableStorageComponent")
	if(variable_storages ~= nil)then
		for k, v in pairs(variable_storages)do
			name_out = ComponentGetValue2(v, "name")
			if(name_out == name)then
				value = ComponentGetValue2(v, "value_bool")
			end
		end
	end
	return value
end

function EntityAddFlag(entity, name)
	variable_storages = EntityGetComponentIncludingDisabled(entity, "VariableStorageComponent")
	has_been_set = false
	if(variable_storages ~= nil)then
		for k, v in pairs(variable_storages)do
			name_out = ComponentGetValue2(v, "name")
			if(name_out == name)then
				ComponentSetValue2(v, "value_bool", true)
				has_been_set = true
			end
		end
	end
	if(has_been_set == false)then
		comp = {}
		comp.name = name
		comp["value_bool"] = true
		EntityAddComponent2(entity, "VariableStorageComponent", comp)
	end
end

function EntityRemoveFlag(entity, name)
	variable_storages = EntityGetComponentIncludingDisabled(entity, "VariableStorageComponent")
	if(variable_storages ~= nil)then
		for k, v in pairs(variable_storages)do
			name_out = ComponentGetValue2(v, "name")
			if(name_out == name)then
				EntityRemoveComponent(entity, v)
			end
		end
	end
end

function GuiGetMousePosition(gui)
	screen_width, screen_height = GuiGetScreenDimensions( gui );
	local x, y = DEBUG_GetMouseWorld()
	local virt_x = MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")
	local virt_y = MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y")
	local scale_x = virt_x / screen_width
	local scale_y = virt_y / screen_height
	local cx, cy = GameGetCameraPos()
	local sx, sy = (x - cx) / scale_x + screen_width / 2 + 1.5, (y - cy) / scale_y + screen_height / 2

	return sx, sy
end

function is_using_gamepad(player)
    local platform_shooter_player = EntityGetFirstComponentIncludingDisabled(player, "PlatformShooterPlayerComponent")
    if platform_shooter_player then
      return ComponentGetValue2(platform_shooter_player, "mHasGamepadControlsPrev")
    end
    return false
end

function EntityGetNamedChild( entity_id, name )
    local children = EntityGetAllChildren( entity_id ) or {};
	if children ~= nil then
		for index,child_entity in pairs( children ) do
			local child_entity_name = EntityGetName( child_entity );
			
			if child_entity_name == name then
				return child_entity;
            end
        end
    end
end

function GetClosestEntityInRadiusWithTag(x, y, radius, tag, ignore)
	ignore = ignore or {}
	local entities = EntityGetInRadiusWithTag(x, y, radius, tag)
	local closest_entity = nil
	local closest_distance = radius
	if entities ~= nil then
		for index,entity_id in pairs(entities) do
			local allow = true
			for k, v in ipairs(ignore)do
				if v == entity_id then
					allow = false
				end
			end

			if(allow)then
				local x2, y2 = EntityGetTransform(entity_id)
				local distance = math.sqrt((x - x2)^2 + (y - y2)^2)
				if distance < closest_distance then
					closest_entity = entity_id
					closest_distance = distance
				end
			end
		end
	end
	return closest_entity
end

function GetEntitiesInRadiusWithTagExcluding(x, y, radius, tag, ignore)
	ignore = ignore or {}
	local entities = EntityGetInRadiusWithTag(x, y, radius, tag)
	local out_entities = {}
	if entities ~= nil then
		for index,entity_id in pairs(entities) do
			local allow = true
			for k, v in ipairs(ignore)do
				if v == entity_id then
					allow = false
				end
			end

			if(allow)then
				table.insert(out_entities, entity_id)
			end
		end
	end
	return out_entities
end

function Integer(value)
	return value > 0.5 and math.ceil(value) or math.floor(value)
end