Jump to content
Alloder.pro: about Allods with love
Search In
  • More options...
Find results that contain...
Find results in...

New program for writers

We turn from quantity to quality and tell you how we will supplement the Allods Team program with rewards in rubles.

More

The new Updater

Let us to introduce the new addon updater software and to share the details

Read more

Alloder 2.0

We have started the process of project evolve, and this relates not only, and not even primarily of the site's view

Read more

Калькулятор рун (RuneCalc)


knight_rider
 Share

Recommended Posts

Доброго времени суток.

Созрела мысль написания внутриигрового калькулятора рун. Заодно решил изучить LUA.

И так вот моя задумка. При открытии окна соединения рун рядышком отображать окно аддона. Аддон читает количество необходимой пыльци, умножает на стоимость одной, считает количество крошки и умножает на стоимость 1й. После этого он суммирует оба значения и мы получаем стомость новой руны в золоте. При смене позиции ползунка аддон доджен пересчитывать значение. Так же хотел добавить editbox для ввода нынешнего курса кристаллов.

После поанировки перешел к реализации. Открыл манул для разрабртчикав и начал искать event, который отвечает за открытие окна соединения рун. Таким образом моя первоначальная задумка рассыпалась прахом.

Единсивенное что я нашел avatar.GetCombineRunesPrice( runeId, crystalCrumbBonus, count ), который, как я понял, работает с номером ячейки из сумки. Т.е. с его помощью можно выделив руну посчитать стоимость руны полгнав ее со значением crystalCrumbBonus в диапазоне [-7,+7]. Но тут возник другой вопрос, на какой event реагирует сумка?

Но мне все же хотелось бы попробовать реализовать с окном соединения, есть какие-нибуть идеи, как это можно реализовать?

Link to comment
Share on other sites

Quote:
При открытии окна соединения рун ..

В документацию посмотрел - и правда скудная информация.

В старых скриптах нашел такой event

Code:
common.RegisterEventHandler( OnScriptRequestRuneCombine, "SCRIPT_REQUEST_RUNE_COMBINE" )

--------------------------------------------------------------------------------

-- SCRIPT_REQUEST_RUNE_COMBINE

function OnScriptRequestRuneCombine( params )

if params.runeSlot and params.instrumentSlot then

-- get params

runeLevel = params.runeLevel

runeSlot = params.runeSlot

runeId = params.runeId

instrumentSlot = params.instrumentSlot

      --....

        end

end

Проверь - вдруг повезет и событие еще работает?

Link to comment
Share on other sites

Это событие отправляется SendEvent'ом библиотеки, например, protectedCommon из стандартного аддона. На него подписываться мы не можем.

То есть, у каждой группы аддонов (стандартные, пользовательские), эм, как бы это правильно назвать, свое независимое "пространство событий". о_0 Чо-т такое, не? :)

Link to comment
Share on other sites

^^

Code:
Global( "wtMainForm", nil )

Global( "wtMainPanel", nil )

Global( "visible", false )

wtMainForm = stateMainForm:GetChildChecked("ContextRuneCombiner2", false )

wtMainPanel = wtMainForm:GetChildChecked("MainPanel", false )

common.RegisterEventHandler( OnTimer, "EVENT_SECOND_TIMER" )

visible = false

-- EVENT HANDLERS

function OnTimer( params )

--LogInfo(wtMainForm:IsVisible(), " ", visible)

if wtMainPanel:IsVisible()  == true and visible == false then

visible = true

LogInfo("Открылось окно")

end

if wtMainPanel:IsVisible() == false and  visible == true then

visible = false

LogInfo("Закрылось окно")

end

end

Link to comment
Share on other sites

Спасибо. Теперь осталось разобраться, как от этого виджета получить информацию о состоянии полей или информацию RuneID и текущее значение ползунка.

Link to comment
Share on other sites

Попробуй получить ссылку на ползунок.. и получай информацию стандартными функциями

Link to comment
Share on other sites

Пробовал покурить гугл, безуспешно. Полазив по форуму получил от виджета следующее

Code:
Info: addon RuneCalc: ContextRuneCombiner2:    GetBackgroundColor:=function: 1366ED80

Info: addon RuneCalc: ContextRuneCombiner2:    Enable:=function: 1366F2A0

Info: addon RuneCalc: ContextRuneCombiner2:    SetFocus:=function: 1366F300

Info: addon RuneCalc: ContextRuneCombiner2:    SetBackgroundTexture:=function: 1366EDE0

Info: addon RuneCalc: ContextRuneCombiner2:    IsFocused:=function: 1366F2E8

Info: addon RuneCalc: ContextRuneCombiner2:    GetNamedChildren:=function: 1366F348

Info: addon RuneCalc: ContextRuneCombiner2:    GetFade:=function: 1366F258

Info: addon RuneCalc: ContextRuneCombiner2:    SetForegroundClearMaskEffect:=function: 1366EE88

Info: addon RuneCalc: ContextRuneCombiner2:    SetForegroundColor:=function: 1366EDC8

Info: addon RuneCalc: ContextRuneCombiner2:    SetPriority:=function: 1366F2D0

Info: addon RuneCalc: ContextRuneCombiner2:    GetParent:=function: 1366F360

Info: addon RuneCalc: ContextRuneCombiner2:    GetName:=function: 1366EF70

Info: addon RuneCalc: ContextRuneCombiner2:    Show:=function: 1366EFB8

Info: addon RuneCalc: ContextRuneCombiner2:    GetRealRect:=function: 1366EEA0

Info: addon RuneCalc: ContextRuneCombiner2:    AddChild:=function: 1366EE10

Info: addon RuneCalc: ContextRuneCombiner2:    IsEnabled:=function: 1366F288

Info: addon RuneCalc: ContextRuneCombiner2:    SetBackgroundColor:=function: 1366ED98

Info: addon RuneCalc: ContextRuneCombiner2:    GetPriority:=function: 1366F2B8

Info: addon RuneCalc: ContextRuneCombiner2:    PlayResizeEffect:=function: 1366F3A8

Info: addon RuneCalc: ContextRuneCombiner2:    SetBackgroundClearMaskEffect:=function: 1366EE70

Info: addon RuneCalc: ContextRuneCombiner2:    FinishMoveEffect:=function: 1366ED10

Info: addon RuneCalc: ContextRuneCombiner2:    SetPlacementPlain:=function: 1366F390

Info: addon RuneCalc: ContextRuneCombiner2:    FinishFadeEffect:=function: 1366ED68

Info: addon RuneCalc: ContextRuneCombiner2:    SetBackgroundBlendEffect:=function: 1366EE40

Info: addon RuneCalc: ContextRuneCombiner2:    CreateWidgetByDesc:=function: 1366EF40

Info: addon RuneCalc: ContextRuneCombiner2:    __index:=table: 1366ECB8

Info: addon RuneCalc: ContextRuneCombiner2:    GetInstanceId:=function: 1366EEE8

Info: addon RuneCalc: ContextRuneCombiner2:    DestroyWidget:=function: 1366EED0

Info: addon RuneCalc: ContextRuneCombiner2:    IsVisible:=function: 1366EFA0

Info: addon RuneCalc: ContextRuneCombiner2:    GetForegroundColor:=function: 1366EDB0

Info: addon RuneCalc: ContextRuneCombiner2:    SetForegroundBlendEffect:=function: 1366EE58

Info: addon RuneCalc: ContextRuneCombiner2:    GetChildUnchecked:=function: 1366F330

Info: addon RuneCalc: ContextRuneCombiner2:    SetForegroundTexture:=function: 1366EE28

Info: addon RuneCalc: ContextRuneCombiner2:    IsEqual:=function: 1366EDF8

Info: addon RuneCalc: ContextRuneCombiner2:    GetChildChecked:=function: 1366F318

Info: addon RuneCalc: ContextRuneCombiner2:    PlayMoveEffect:=function: 1366ECF8

Info: addon RuneCalc: ContextRuneCombiner2:    SetFade:=function: 1366F270

Info: addon RuneCalc: ContextRuneCombiner2:    GetWidgetDesc:=function: 1366EEB8

Info: addon RuneCalc: ContextRuneCombiner2:    GetPlacementPlain:=function: 1366F378

Info: addon RuneCalc: ContextRuneCombiner2:    __gc:=function: 1366EF00

Info: addon RuneCalc: ContextRuneCombiner2:    SetName:=function: 1366EF88

Info: addon RuneCalc: ContextRuneCombiner2:    FinishResizeEffect:=function: 1366ECE0

Info: addon RuneCalc: ContextRuneCombiner2:    PlayFadeEffect:=function: 1366ED50

Info: addon RuneCalc: ContextRuneCombiner2:    _:=userdata: 1367A578{userdata}

Можете направть меня в нужное русло? Что почитать? Есть ли из работающих аддоны, которые получают ссылки на эелементы другого виджета?

Ну в общем без примера не обойтись :-(

P.S. я только начал открывать для себя Lua

Link to comment
Share on other sites

Почитать.. и посмотреть скрипты простых аддонов (понять и помодифицировать) : AutoPetAttack(очень простой аддон с хорошими комментариями),EnemyBehind, DDView.. потом и все остальные станут твоими учебниками : ).. Код открытый - поэтому мы все друг у друга учимся.

Вывод списка "детей" ContextRuneCombiner2 в mods.txt

Code:
getAllChildrensOfWidget("", ContextRuneCombiner2)

---------------

function getAllChildrensOfWidget(tab,widget) -- (с) icreator

local childrens = widget:GetNamedChildren()

for _, w in childrens do

local tab1 = tab .. ":" .. w:GetName()

LogInfo (tab1)

getAllChildrensOfWidget(tab1,w)

end

end

Узнаешь имя ползунка, и функцией GetChildChecked(см. справку в "Allods Online\data\Mods\Docs\ModdingDocuments\") получишь ссылку в переменную..

Link to comment
Share on other sites

Спасибо, буду изучать

Code:
Info: addon RuneCalc: :MainPanel

Info: addon RuneCalc: :MainPanel:CrystalTube

Info: addon RuneCalc: :MainPanel:CrystalTube:FlowHighlight

Info: addon RuneCalc: :MainPanel:GoldTube

Info: addon RuneCalc: :MainPanel:GoldTube:FlowHighlight

Info: addon RuneCalc: :MainPanel:GoldenCorner

Info: addon RuneCalc: :MainPanel:GoldenCorner:CornerCross

Info: addon RuneCalc: :MainPanel:Reset

Info: addon RuneCalc: :MainPanel:WindowHeader

Info: addon RuneCalc: :MainPanel:WindowHeader:HeaderText

Info: addon RuneCalc: :MainPanel:Combine

Info: addon RuneCalc: :MainPanel:GoldenDust

Info: addon RuneCalc: :MainPanel:GoldenDust:Need

Info: addon RuneCalc: :MainPanel:GoldenDust:ItemTexture

Info: addon RuneCalc: :MainPanel:GoldenDust:Have

Info: addon RuneCalc: :MainPanel:LesserRune

Info: addon RuneCalc: :MainPanel:LesserRune:RuneLevel

Info: addon RuneCalc: :MainPanel:LesserRune:Need

Info: addon RuneCalc: :MainPanel:LesserRune:ItemTexture

Info: addon RuneCalc: :MainPanel:LesserRune:RuneGlow

Info: addon RuneCalc: :MainPanel:LesserRune:Have

Info: addon RuneCalc: :MainPanel:CrystalDust

Info: addon RuneCalc: :MainPanel:CrystalDust:Need

Info: addon RuneCalc: :MainPanel:CrystalDust:ItemTexture

Info: addon RuneCalc: :MainPanel:CrystalDust:Have

Info: addon RuneCalc: :MainPanel:HigherRune

Info: addon RuneCalc: :MainPanel:HigherRune:ButtonScrollLeft

Info: addon RuneCalc: :MainPanel:HigherRune:ButtonScrollRight

Info: addon RuneCalc: :MainPanel:HigherRune:RuneLevel

Info: addon RuneCalc: :MainPanel:HigherRune:ItemTexture

Info: addon RuneCalc: :MainPanel:HigherRune:RuneGlow

Info: addon RuneCalc: :MainPanel:HigherRune:Need

Info: addon RuneCalc: :MainPanel:Chamber

Info: addon RuneCalc: :MainPanel:Chamber:ChamberOverlay

Info: addon RuneCalc: :MainPanel:Chamber:ChamberOverlay:ChamberGlow

Info: addon RuneCalc: :MainPanel:Chamber:ChamberOverlay:FlowHighlight

Info: addon RuneCalc: :MainPanel:Chamber:Slider

Info: addon RuneCalc: :MainPanel:Chamber:ChamberMixed

Info: addon RuneCalc: :MainPanel:Chamber:ChamberMixed:MixedCrystal

Info: addon RuneCalc: :MainPanel:Chamber:ChamberMixed:MixedBoth

Info: addon RuneCalc: :MainPanel:Chamber:ChamberMixed:MixedGold

По сути мне необходимо GoldenDust:Need и CrystalDust:Need. Теперь буду копать дальше
Link to comment
Share on other sites

Хотел получить числовове значение из строги при помощи GetValuedText( ). Полазив по форуму понял, что разрабы не доработали API и эта функция безполезна. Перешел к варианту avatar.GetCombineRunesPrice( runeId, crystalCrumbBonus, count )

crystalCrumbBonus - значение слайдера, удалось получить на легке;

count - количество создаваемых рун, получить не получилось по причине все того-же GetValuedText( );

runeId - id предмета в сумке. Получаю по методу, описанному в аддоне AucEDSman. Для использования предмета в аддоне его придварительно надо перетащи в свободную ячейку.

Может кто-нибуть знает способ получть индекс слота в инвентаре, который находится под мышкой, по возможности в момент надатия левой клавиши?

Читал это, но ничего нового не нашел

upd: Идеально было бы извлечь объект из ContextRuneCombiner2, но достучатся до переменных виджета не удалось

Link to comment
Share on other sites

Прокатит?

Code:

--local itemValObj = GetValuedText( ) --?

local wString = itemValObj:GetText()

local result1 = common.GetIntFromWString( wString )

Quote:
Может кто-нибуть знает способ получть индекс слота в инвентаре, который находится под мышкой, по возможности в момент надатия левой клавиши?

Если получить виджеты из всплывающей подсказки (инфо о предмете).. то получать предмет теоретически можно ^^

Link to comment
Share on other sites

Code:

local itemValObj = wtRuneCounter:GetValuedText( )
local wString = itemValObj:GetText()
local result1 = common.GetIntFromWString( wString )

wtRuneCounter - виджет, из которого необходимо получить строку.
получаю в log
Code:
Error: addon RuneCalc: Error while running the chunk
Error: addon RuneCalc:    [string "Mods/Addons/RuneCalc/RuneCalc.lua"] :56: attempt to call method `GetText' (a nil value)
Error: addon RuneCalc:   func: GetText, method, line: -1, defined: C, line: -1,  [C] 
Error: addon RuneCalc:     func: OnTimer, global, line: 56, defined: Lua, line: 39,  [string "Mods/Addons/RuneCalc/RuneCalc.lua"] 

Может выполняю не правильную последовательность действыи?
GetValuedText возвращает переменную типа userdata, может из-за этого не получается
Link to comment
Share on other sites

Quote:
attempt to call method `GetText' (a nil value)

хм.. говорит что такой функции нет, хотя в
"/data/Mods/Docs/ModdingDocuments/LuaApi/FunctionValuedObjectGetText.html"
такой имеется.. Неужели тоже закрытая функция? хм.. Печально .. что нас оставили без этой функции :(
.. покопал API
Code:
local wString = itemValObj:GetId() -- nill ???
Link to comment
Share on other sites

Code:

local itemValObj = wtRuneCounter:GetValuedText( )
local wString = itemValObj:GetId()
LogInfo( "itemValObj = ", wString)

выдало в лог
Code:

Error: addon RuneCalc: Error while running the chunk
Error: addon RuneCalc:    [string "Mods/Addons/RuneCalc/RuneCalc.lua"] :65: attempt to call method `GetId' (a nil value)
Error: addon RuneCalc:   func: GetId, method, line: -1, defined: C, line: -1,  [C] 
Error: addon RuneCalc:     func: OnTimer, global, line: 65, defined: Lua, line: 48,  [string "Mods/Addons/RuneCalc/RuneCalc.lua"] 

проанализировал itemValObj найденой на форуме функцией
Code:
researchObj("itemValObj",itemValObj)

Вот что получил. В обьекте нет таких функций
Code:

Info: addon RuneCalc: itemValObj    SetFormat:=function: 0BA55860
Info: addon RuneCalc: itemValObj    SetClassVal:=function: 08B27FF8
Info: addon RuneCalc: itemValObj    __gc:=function: 2132BC18
Info: addon RuneCalc: itemValObj    SetVal:=function: 13D38B78
Info: addon RuneCalc: itemValObj    CreateCopy:=function: 1EB73230
Info: addon RuneCalc: itemValObj    __index:=table: 1E62D2D0
Info: addon RuneCalc: itemValObj    ClearValues:=function: 13D38B30
Info: addon RuneCalc: itemValObj    _:=userdata: 0E400B58{userdata}


Вот код того, что есть. Сейчас работаю над GUI.
Code:
---------------------------------------------------------------------------------
-- GLOBALS
---------------------------------------------------------------------------------

-- Панели ----------------------------
Global( "wtMainPanel", nil )
Global( "wtgoldDust", nil )
Global( "wtcrystalCrumb", nil )
Global( "wtruneName", nil )
Global( "wtContextRuneCombiner2", nil )
Global( "wtSlider", nil )
Global( "wtRuneCounter", nil )
-- Other ---------------------------
Global( "visible", false )

Global( "ItemId", nil ) --- Идентификатор последней активной ячейки
Global( "RuneId", nil ) --- Идентификатор руны
Global( "RuneName", nil ) --- Идентификатор руны
Global( "PriseOf10kGoldenDust", 90000 ) --- Цена 1000 золотой пыли в деньгах
Global( "PriseOf1CrystalCrumb", 3 ) --- Цена 1 кристаллической крошки в кристаллах
Global( "PriseOf1Crystal", 80000 ) --- Цена 1 кристалла в деньгах
Global( "goldDust", nil ) --- стоимость требуемой золотой пыльцы в деньгах
Global( "crystalCrumb", nil ) --- стоимость требуемой кристалической крошки в деньгах
Global( "totalPrice", nil ) --- Идентификатор руны

---------------------------------------------------------------------------------
-- EVENT HANDLERS
---------------------------------------------------------------------------------

function ToWS( str )
if str then
return userMods.ToWString( str )
else
return userMods.ToWString( "Not String" )
end
end

function ToMoney( value )
local result={Gold,Silver,Copper}
result.Gold = math.floor(value / 10000)
value =value - result.Gold
result.Silver = math.floor(value / 100)
value = value - result.Silver
result.Copper = value
end

-- Каждую секунду
function OnTimer( params )
if wtContextRuneCombiner2:IsVisible()  == true and visible == false then
visible = true
LogInfo("Открылось окно")
end
if wtContextRuneCombiner2:IsVisible() == false and  visible == true then
visible = false
end
if wtContextRuneCombiner2:IsVisible()  == true and visible == true then
local count = wtSlider:GetPos()
if RuneId then
local itemValObj = wtRuneCounter:GetValuedText( )
researchObj("itemValObj",itemValObj)
local price = avatar.GetCombineRunesPrice( RuneId, count - 7, 1 )
--LogInfo( "gold dust = ", price.goldDust, " crystal crumb = ", price.crystalCrumb, " slide = ", count )
goldDust = price.goldDust * ( PriseOf10kGoldenDust / 1000 ) 
crystalCrumb = price.crystalCrumb * ( PriseOf1CrystalCrumb * PriseOf1Crystal )
totalPrice = goldDust + crystalCrumb
wtgoldDust:SetVal( "value", common.FormatInt( goldDust , "%d" ) )
wtcrystalCrumb:SetVal( "value", common.FormatInt( crystalCrumb , "%d" ) )
--LogInfo( "count = ", goldDust," crystalCrumb = ", crystalCrumb," totalPrice = ", totalPrice )
end
end
end

-- При скрытии интерфейса (ALT+Z)
function OnToggleUI( params )
mainForm:Show( params.visible )
end

-- Запрос используемой памяти от "AddonManager"
function OnAMMemUsageRequest( params )
userMods.SendEvent( "U_EVENT_ADDON_MEM_USAGE_RESPONSE", { sender = common.GetAddonName(), memUsage = gcinfo() } )
end

-- Реакция на перемещение предмета в сумке
function OnInventory  ( params )
ItemId = avatar.GetInventoryItemId( params.slot )
local itemInfo = avatar.GetItemInfo( ItemId )
if itemInfo.runeInfo then
RuneId = ItemId
RuneName = itemInfo.name
end
end
---------------------------------------------------------------------------------
-- INITIALIZATION
---------------------------------------------------------------------------------
function Init()

wtMainPanel = mainForm:GetChildChecked( "MainPanel" , false )

wtContextRuneCombiner2 = stateMainForm:GetChildChecked("ContextRuneCombiner2", false )
wtContextRuneCombiner2 = wtContextRuneCombiner2:GetChildChecked("MainPanel", false )
wtSlider = wtContextRuneCombiner2:GetChildChecked("Slider", true )
wtRuneCounter = wtContextRuneCombiner2:GetChildChecked("HigherRune", false )
wtRuneCounter = wtRuneCounter:GetChildChecked("Need", false )

common.RegisterEventHandler( OnTimer, "EVENT_SECOND_TIMER" )
common.RegisterEventHandler( OnInventory , "EVENT_INVENTORY_ITEM_CHANGED" ) 

-- Скрывать по "ALT+Z"
common.RegisterEventHandler( OnToggleUI, "SCRIPT_TOGGLE_UI" )

-- События "AddonManager"
common.RegisterEventHandler( OnAMMemUsageRequest, "U_EVENT_ADDON_MEM_USAGE_REQUEST" )
end
---------------------------------------------------------------------------------
Init()
---------------------------------------------------------------------------------
Link to comment
Share on other sites

О_О

Это вы из ValuedText`а решили чето выколупать? Удачи вам желаю

С чего вдруг mehael решил, что оно является ValuedObject`ом?

Нет в пользовательском АПИ функций, добывающих из ValuedText какую-либо инфу

Link to comment
Share on other sites

их вытянуть можно, но не пользовательскими функциями. Вот выдержки из манула

Code:
-- класс

TextViewSafe

-- семантика

function GetValuedText( self )

-- входные параметры отсутствуют

-- возвращаемое значение

ValuedText - текст

-- пример

local text = wtTextView:GetValuedText()

LogInfo( debugCommon.FromValuedText( text, false ) )

Link to comment
Share on other sites

[typevaluedtext.html]

Quote:
ValuedText

Форматированная строка с подстановочными значениями. Специальный вариант userdata .

Ога, текст

Quote:
не пользовательскими функциями

И о чем тогда разговор? Ты какими то другими функциями можешь пользоваться?

Link to comment
Share on other sites

Сырая альфа версия.

Для установки поместить pak файл в папку addons

n9vM7LWQ.png

Недостатки:

- Стоимость крошки в кристаллах и курс кристалов в игровой валюте пока заданы в коде.

- Для корректного определения руны, которая обрабатывается, ее необходимо переместить в свободную ячейку.

- Кривовато выводятся цифровые значения

- Нет защиты "от дурака"

ToDo List:

- создать окно конфига, в котором будет задаваться их стоимость с возможностью сохранения.

- по возможности при начале создания руны автоматически выбирать самый выгодный вариант

Link to comment
Share on other sites

можно сказать предрелизная версия.

Сделано:

- окно конфига, в котором задается стоимость компрнентов с сохранением параметров в глобальную секцию user.cfg.

- поправил вывод числовых значений

7tsvjFDU.png

Недостатки:

- Для корректного определения руны, которая обрабатывается, ее необходимо переместить в свободную ячейку.

- Нет защиты "от дурака"

ToDo List:

- по возможности API при начале создания руны автоматически выбирать самый выгодный вариант

- ElitLine выровняна по левому краю, надо сделать по правому. Пока не понял как.

- Навести порядок в переменных и коде

На зарубежных серверах не играл, поэтому не в курсе, актуален аддон для них или нет. При необходимости сделаю его мультиязычным.

SLA и Skillcoder уже не появлялись. К кому обращаться по поводу публикации на главной?

UPD

перезалил 27.01.11 в 13.00 по киеву. при старте игры теперь аддон не отображается

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

By using our site you agree to the Terms of Use