Beschreibung
Normaler Weise haben Interaktive Objekte immer ihr Handsymbol und es steht immer der selbe vordefinierte Text da. In DIE SIEDLER - Reich des Ostens kommen Handelsposten und auffüllbare Minen hinzu. Aber wie wäre es, wenn man den Text des Tooltip und das Bild auf dem Button selbst bestimmen könnte? Das wird nun möglich sein.
Des weiteren ist es seit der Version 3.0 möglich für die selbst gebauten Interaktiven Objekte Kosten und Belohnungen zu definieren, ähnlich wie bei den normalen Objekten.
Wichtig: Alles was nicht I_X_ im Namen hat, gilt für den Assistenten nicht als interaktives Objekt!
Aktuelle Version: 3.1
SetupInteractiveObject
Die Funktion SetupInteractiveObject setzt die Definition des Objektes fest. Sie wird im globalen Skript aufgerufen und kann sowohl normale interaktive Objekte als auch selbsterstellte mit allem Drum und Dran einstellen. Das Skript erkennt von selbst, welchen Fall es behandeln muss.
Als erstes Argument wird der Skriptname der Entity übergeben, der eine Aktion zugewiesen wird. Das zweite Argument ist ein Table mit den Vereinbarungen zu dem Objekt. Alle Einträge sind optional, also könnte der Table theoretisch auch leer sein, was aber wenig Sinn macht ;) . Bei einem weggelassenen Eintrag wird ein Standartwert verwendet.
Argumententabelle
Argument |
Beschreibung |
title |
Zeichenkette mit dem im Tooltip anzuzeigenden Titel. |
text |
Zeichenkette mit dem im Tooltip anzuzeigenden Text. Das könnte z.B. eine Information sein, was passiert, wenn der Schalter getätigt wird. |
texture |
Wenn eine andere Textur für den Button genutzt werden soll, müssen hier die Koordinaten als Table übergeben werden. Für die 3 Koordinate gilt:
- {x, y, 0} Textur aus dem Hauptspiel
- {x, y, 1} Textur aus der Erweiterung
- {x, y, 2} Externe Grafik (Beta-Stadium)
|
state |
Der Status gibt an, wie das Objekt benutzt werden kann:
- 0 : Kann nur vom Ritter benutzt werden
- 1 : Kann immer benutzt werden
- 2 : kann nicht benutzt werden
Dies zeigt keine Wirkung bei selbstgebauten Objekten!
|
distance |
Die Auslösedistanz für das interaktive Objekt.
Bei selbstgebauten Objekten muss diese Variable nil sein, damit das Objekt immer benutzbar ist. Sonst kann es nur von einem Ritter benutzt werden. |
rewardType |
Typ der gefundenen Belohnung. |
rewardAmount |
Anzahl an Einheiten der gefundenen Belohnung. |
costType1 |
Typ der ersten Resource, die zum aktivieren benötigt wird. |
costType2 |
Typ der ersten Resource, die zum aktivieren benötigt wird. |
costAmount1 |
Anzahl des ersten Rohstoffs zur Aktivierung. |
costAmount2 |
Anzahl des zweiten Rohstoffs zur Aktivierung. |
callback |
Eine Aktion beim betätigen des Schalters auslösen. Mit dem Callback kann man z.B. Tore öffnen. An die Funktion wird ein Table _table als Argument übergeben, der alles beinhaltet, was bei der Erstellung vereinbart wurde, plus den Namen des Objektes abzurufen mit _table.name . _table ist natürlich ein frei wählbarer Bezeichner und kann auch t oder xyz sein. |
Beispiel
Ein kleines Beispiel einer Ruine, die über die Funktion initialisiert wird. Dabei ist es unerheblich ob "echtes" interaktives Objekt oder nicht.
SetupInteractiveObject("ruin1",{
rewardType = Goods.G_Gold,
rewardAmount = 300,
callback = function(t)
Logic.DEBUG_AddNote("Ihr habt etwas Gold Gefunden!")
end
})
Functionscode
Der Funktionscode ist geteilt in globales und lokales Skript.
Es müssen die jeweiligen Teile in die vorgesehene Skriptumgebung kopiert werden.
Globales Skript
IO.PlayerID = 1
function InteractiveObjectActivate(eName)
if not IsExisting(eName) then
return
end
Logic.InteractiveObjectSetAvailability(GetID(eName),true)
for i = 1, 8 do
Logic.InteractiveObjectSetPlayerState(GetID(eName),i,0)
end
end
function InteractiveObjectDeactivate(eName)
if not IsExisting(eName) then
return
end
Logic.InteractiveObjectSetAvailability(GetID(eName),false)
for i = 1, 8 do
Logic.InteractiveObjectSetPlayerState(GetID(eName),i,2)
end
end
function GameCallback_OnObjectInteraction(eID,pID)
OnInteractiveObjectOpened(eID,pID)
OnTreasureFound(eID,pID)
local eName = Logic.GetEntityName(eID)
for k,v in pairs(IO)do
if k == eName then
if not IO[eName].Used then
IO[eName].callback(IO[eName])
IO[eName].Used = true
end
end
end
end
function SetupInteractiveObject(eName,t)
assert(IsExisting(eName))
local eID = GetID(eName)
if not t.title then
t.title = "Interaktives Objekt"
end
if not t.text then
t.text = "Dieses Objekt kann benutzt werden."
end
if not t.texture then
t.texture = {14,10,0}
end
if not t.texture[3] then
t.texture[3] = 0
end
if not t.state then
t.state = 0
end
if not t.callback then
t.callback = function()end
end
t.name = eName;
if Logic.IsInteractiveObject(eID) == true then
-- init object
t.distance = t.distance or 1600
t.time = t.time or 0
t.rewardType = t.rewardType or nil
t.rewardAmount = t.rewardAmount or nil
t.costType1 = t.costType1 or nil
t.costAmount1 = t.costAmount1 or nil
t.costType2 = t.costType2 or nil
t.costAmount2 = t.costAmount2 or nil
Logic.InteractiveObjectClearCosts(eID)
Logic.InteractiveObjectClearRewards(eID)
Logic.InteractiveObjectSetInteractionDistance(eID,t.distance)
Logic.InteractiveObjectSetTimeToOpen(eID,t.time)
Logic.InteractiveObjectAddRewards(eID,t.rewardType,t.rewardAmount)
Logic.InteractiveObjectAddCosts(eID,t.costType1,t.costAmount1)
Logic.InteractiveObjectAddCosts(eID,t.costType2,t.costAmount2)
Logic.InteractiveObjectSetAvailability(eID,true)
Logic.InteractiveObjectSetPlayerState(eID,IO.PlayerID,t.state)
Logic.InteractiveObjectSetRewardResourceCartType(eID,Entities.U_ResourceMerchant)
Logic.InteractiveObjectSetRewardGoldCartType(eID,Entities.U_GoldCart)
Logic.InteractiveObjectSetCostGoldCartType(eID, Entities.U_GoldCart)
Logic.InteractiveObjectSetCostResourceCartType(eID,Entities.U_ResourceMerchant)
table.insert(HiddenTreasures,eID)
--save object
IO[eName] = t
-- execute description
Logic.ExecuteInLuaLocalState([[
SetupInteractiveObject("]]..eName..[[",{
Title = "]]..t.title..[[",
Text = "]]..t.text..[[",
Texture = {]]..t.texture[1]..[[,]]..t.texture[2]..[[,]]..t.texture[3]..[[},
})
]])
else
t.distance = t.distance or 1600
t.rewardType = t.rewardType or nil
t.rewardAmount = t.rewardAmount or nil
t.costType1 = t.costType1 or nil
t.costAmount1 = t.costAmount1 or nil
t.costType2 = t.costType2 or nil
t.costAmount2 = t.costAmount2 or nil
-- save object
IO[eName] = t
-- execute description
Logic.ExecuteInLuaLocalState([[
SetupInteractiveObject("]]..eName..[[",{
Title = "]]..t.title..[[",
Text = "]]..t.text..[[",
Costs = {]]..tostring(t.costType1)..[[,]]..tostring(t.costAmount1)..[[,]]..tostring(t.costType2)..[[,]]..tostring(t.costAmount2)..[[},
Reward = {]]..tostring(t.rewardType)..[[,]]..tostring(t.rewardAmount)..[[},
Texture = {]]..t.texture[1]..[[,]]..t.texture[2]..[[,]]..t.texture[3]..[[},
Distance = ]]..t.distance..[[,
Callback = "CallbackInGlobalLua",
})
]])
end
end
Lokales Skript
function SetupInteractiveObject(eName,t)
g_Interaction.ActiveObjectsOnScreen = g_Interaction.ActiveObjectsOnScreen or {}
assert(IsExisting(eName),"SetupInteractiveObject: Dein Objekt '"..eName.."' existiert nicht auf der Karte!")
local eID = GetEntityId(eName)
if not IO.Control then
ControlInteractiveObject()
IO.Control = true
end
if not t.Title then
t.Title = "Interaktives Objekt"
end
if not t.Text then
t.Text = "Dieses Objekt kann benutzt werden."
end
if not t.Texture then
t.Texture = {14, 10}
end
if not t.Costs then
t.Costs = {}
end
if not t.Callback then
t.Callback = function()end
end
IO[eName] = t
end
function RemoveInteractiveObject(eName)
for k,v in pairs(IO) do
if k == eName then
IO[eName] = nil
end
end
end
function ControlInteractiveObject()
GUI_Tooltip.SetNameAndDescription_OrigtwAIO = GUI_Tooltip.SetNameAndDescription
GUI_Tooltip.SetNameAndDescription = function(_TooltipNameWidget, _TooltipDescriptionWidget, _OptionalTextKeyName, _OptionalDisabledTextKeyName, _OptionalMissionTextFileBoolean)
if XGUIEng.GetWidgetPathByID(XGUIEng.GetCurrentWidgetID()) == "/InGame/Root/Normal/InteractiveObjects/1"
or XGUIEng.GetWidgetPathByID(XGUIEng.GetCurrentWidgetID()) == "/InGame/Root/Normal/InteractiveObjects/2" then
GUI_Tooltip.SetNameAndDescription_OrigtwAIO(_TooltipNameWidget, _TooltipDescriptionWidget, _OptionalTextKeyName, _OptionalDisabledTextKeyName, _OptionalMissionTextFileBoolean)
local number = tonumber(XGUIEng.GetWidgetNameByID(XGUIEng.GetCurrentWidgetID()))
local objectID = g_Interaction.ActiveObjectsOnScreen[number]
for k,v in pairs(IO) do
if objectID == GetEntityId(k)then
XGUIEng.SetText(_TooltipNameWidget, Umlaute("{center}"..IO[k].Title))
XGUIEng.SetText(_TooltipDescriptionWidget, Umlaute(IO[k].Text))
local TTH = XGUIEng.GetTextHeight(_TooltipDescriptionWidget, true)
local W, H = XGUIEng.GetWidgetSize(_TooltipDescriptionWidget)
XGUIEng.SetWidgetSize(_TooltipDescriptionWidget, W, TTH)
end
end
else
GUI_Tooltip.SetNameAndDescription_OrigtwAIO(_TooltipNameWidget, _TooltipDescriptionWidget, _OptionalTextKeyName, _OptionalDisabledTextKeyName, _OptionalMissionTextFileBoolean)
end
end
GUI_Interaction.InteractiveObjectUpdate_OrigtwAIO = GUI_Interaction.InteractiveObjectUpdate
GUI_Interaction.InteractiveObjectUpdate = function()
GUI_Interaction.InteractiveObjectUpdate_OrigtwAIO()
local pID = GUI.GetPlayerID()
for k,v in pairs(IO)do
local eType = Logic.GetEntityType(GetEntityId(k))
local eTypeName = Logic.GetEntityTypeName(eType)
for j=1, #g_Interaction.ActiveObjectsOnScreen do
local path = "/InGame/Root/Normal/InteractiveObjects/"..j
if XGUIEng.IsWidgetExisting(path) == 1 then
local objectID = g_Interaction.ActiveObjectsOnScreen[j]
local entityName = Logic.GetEntityName(objectID)
if k == entityName then
UserSetButtonTexture(path,IO[k].Texture)
end
end
end
if eTypeName then
if not(string.find(eTypeName,"I_X_")) and not(string.find(eTypeName,"Mine")) then
if IO[k].Distance ~= nil and IO[k].Distance > 0 then
local pos = GetPosition(k)
local entities = {Logic.GetPlayerEntitiesInArea(pID,0,pos.X,pos.Y,IO[k].Distance,16)}
local found = false
if entities[1] > 0 then
for i=1,#entities do
if Logic.IsEntityInCategory(entities[i],EntityCategories.Hero) == 1 then
found = true
end
end
end
if found and not IO[k].Used then
ScriptCallback_ObjectInteraction(pID,GetEntityId(k))
else
ScriptCallback_CloseObjectInteraction(pID,GetEntityId(k))
end
else
if not IO[k].Used then
ScriptCallback_ObjectInteraction(pID,GetEntityId(k))
else
ScriptCallback_CloseObjectInteraction(pID,GetEntityId(k))
end
end
end
end
end
end
GUI_Interaction.InteractiveObjectMouseOver_OrigtwAIO = GUI_Interaction.InteractiveObjectMouseOver
GUI_Interaction.InteractiveObjectMouseOver = function()
local ButtonNumber = tonumber(XGUIEng.GetWidgetNameByID(XGUIEng.GetCurrentWidgetID()))
local eID = g_Interaction.ActiveObjectsOnScreen[ButtonNumber]
local eName = Logic.GetEntityName(eID)
local pID = GUI.GetPlayerID()
if Logic.IsInteractiveObject(eID) then
GUI_Interaction.InteractiveObjectMouseOver_OrigtwAIO()
else
if IO[eName] and IO[eName].Used ~= true then
local CurrentWidgetID = XGUIEng.GetCurrentWidgetID()
local TooltipTextKey = "InteractiveObjectAvailable"
local Costs = {}
if IO[eName].Costs[1] ~= nil then
table.insert(Costs,IO[eName].Costs[1])
table.insert(Costs,IO[eName].Costs[2])
end
if IO[eName].Costs[3] ~= nil then
table.insert(Costs,IO[eName].Costs[3])
table.insert(Costs,IO[eName].Costs[4])
end
local CheckSettlement
if Costs and Costs[1]
and Logic.GetGoodCategoryForGoodType(Costs[1]) ~= GoodCategories.GC_Resource then
CheckSettlement = true
end
GUI_Tooltip.TooltipBuy(Costs, TooltipTextKey, nil, nil, CheckSettlement)
end
end
end
GUI_Interaction.InteractiveObjectClicked_OrigtwAIO = GUI_Interaction.InteractiveObjectClicked
GUI_Interaction.InteractiveObjectClicked = function()
GUI_Interaction.InteractiveObjectClicked_OrigtwAIO()
local i = tonumber(XGUIEng.GetWidgetNameByID(XGUIEng.GetCurrentWidgetID()))
local eID = g_Interaction.ActiveObjectsOnScreen[i]
local pID = GUI.GetPlayerID()
for k,v in pairs(IO)do
if eID == GetEntityId(k)then
local Reward = {}
if IO[k].Reward and IO[k].Reward[1] ~= nil then
table.insert(Reward,IO[k].Reward[1])
table.insert(Reward,IO[k].Reward[2])
end
local CheckSettlement
if IO[k].Costs and IO[k].Costs[1] then
if Logic.GetGoodCategoryForGoodType(IO[k].Costs[1]) ~= GoodCategories.GC_Resource then
CheckSettlement = true
end
local Costs = {}
if IO[k].Costs[1] ~= nil then
table.insert(Costs,IO[k].Costs[1])
table.insert(Costs,IO[k].Costs[2])
end
if IO[k].Costs[3] ~= nil then
table.insert(Costs,IO[k].Costs[3])
table.insert(Costs,IO[k].Costs[4])
end
local CanBuyBoolean, CanNotBuyString = AreCostsAffordable(Costs,CheckSettlement)
if CanBuyBoolean == true then
-- remove costs
if Costs[1] ~= nil then
if Logic.GetGoodCategoryForGoodType(Costs[1]) ~= GoodCategories.GC_Resource and Costs[1] ~= Goods.G_Gold then
local buildings = GetPlayerEntities(pID,0)
local goodAmount = Costs[2]
for i=1,#buildings do
if Logic.IsBuilding(buildings[i]) == 1 and goodAmount > 0 then
if Logic.GetBuildingProduct(buildings[i]) == Costs[1] then
local goodAmountInBuilding = Logic.GetAmountOnOutStockByIndex(buildings[i],0)
for j=1,goodAmountInBuilding do
GUI.SendScriptCommand("Logic.RemoveGoodFromStock("..buildings[i]..","..Costs[1]..",1)")
goodAmount = goodAmount -1
end
end
end
end
else
GUI.SendScriptCommand("AddGood("..IO[k].Costs[1]..",-"..IO[k].Costs[2]..","..pID..")")
end
end
if Costs[3] ~= nil then
if Logic.GetGoodCategoryForGoodType(Costs[3]) ~= GoodCategories.GC_Resource and Costs[3] ~= Goods.G_Gold then
local buildings = GetPlayerEntities(pID,0)
local goodAmount = Costs[4]
for i=1,#buildings do
if Logic.IsBuilding(buildings[i]) == 1 and goodAmount > 0 then
if Logic.GetBuildingProduct(buildings[i]) == Costs[3] then
local goodAmountInBuilding = Logic.GetAmountOnOutStockByIndex(buildings[i],0)
for j=1,goodAmountInBuilding do
GUI.SendScriptCommand("Logic.RemoveGoodFromStock("..buildings[i]..","..Costs[3]..",1)")
goodAmount = goodAmount -1
end
end
end
end
else
GUI.SendScriptCommand("AddGood("..IO[k].Costs[3]..",-"..IO[k].Costs[4]..","..pID..")")
end
end
-- reward
if #Reward > 0 then
GUI.SendScriptCommand([[
local goodAmount = ]]..Reward[2]..[[
local goodType = ]]..Reward[1]..[[
local pos = GetPosition("]]..k..[[")
local resCat = Logic.GetGoodCategoryForGoodType(goodType)
local ID
if resCat == GoodCategories.GC_Resource then
ID = Logic.CreateEntityOnUnblockedLand(Entities.U_ResourceMerchant, pos.X, pos.Y,0,]]..pID..[[)
elseif goodType == Goods.G_Medicine then
ID = Logic.CreateEntityOnUnblockedLand(Entities.U_Medicus, pos.X, pos.Y,0,]]..pID..[[)
elseif goodType == Goods.G_Gold then
ID = Logic.CreateEntityOnUnblockedLand(Entities.U_GoldCart, pos.X, pos.Y,0,]]..pID..[[)
else
ID = Logic.CreateEntityOnUnblockedLand(Entities.U_Marketer, pos.X, pos.Y,0,]]..pID..[[)
end
Logic.HireMerchant(ID,]]..pID..[[,goodType,goodAmount,]]..pID..[[)
]])
end
if Logic.IsInteractiveObject(eID) ~= true then
Sound.FXPlay2DSound( "ui\\menu_left_prestige")
end
-- do callback
if type(IO[k].Callback) == "string" then
GUI.SendScriptCommand("IO['"..k.."'].callback(IO['"..k.."'])")
else
IO[k].Callback(IO[k])
end
IO[k].Used = true
else
Message(CanNotBuyString)
end
else
-- reward
if #Reward > 0 then
GUI.SendScriptCommand([[
local goodAmount = ]]..Reward[2]..[[
local goodType = ]]..Reward[1]..[[
local pos = GetPosition("]]..k..[[")
local resCat = Logic.GetGoodCategoryForGoodType(goodType)
local ID
if resCat == GoodCategories.GC_Resource then
ID = Logic.CreateEntityOnUnblockedLand(Entities.U_ResourceMerchant, pos.X, pos.Y,0,]]..pID..[[)
elseif goodType == Goods.G_Medicine then
ID = Logic.CreateEntityOnUnblockedLand(Entities.U_Medicus, pos.X, pos.Y,0,]]..pID..[[)
elseif goodType == Goods.G_Gold then
ID = Logic.CreateEntityOnUnblockedLand(Entities.U_GoldCart, pos.X, pos.Y,0,]]..pID..[[)
else
ID = Logic.CreateEntityOnUnblockedLand(Entities.U_Marketer, pos.X, pos.Y,0,]]..pID..[[)
end
Logic.HireMerchant(ID,]]..pID..[[,goodType,goodAmount,]]..pID..[[)
]])
end
if Logic.IsInteractiveObject(eID) ~= true then
Sound.FXPlay2DSound( "ui\\menu_left_prestige")
end
-- do callback
if type(IO[k].Callback) == "string" then
GUI.SendScriptCommand("IO['"..k.."'].callback(IO['"..k.."'])")
else
IO[k].Callback(IO[k])
end
IO[k].Used = true
end
end
end
end
end
function UserSetButtonTexture(widget, coord, size, file)
assert((type(widget) == "string" or type(widget) == "number"));
local mapname = Framework.GetCurrentMapName();
local wID = XGUIEng.GetWidgetID(widget);
if coord[3] == nil then coord[3] = 0 end
if size == nil then size = 64 end
local path = "C:\\Settlers RoaE\\"..mapname.."\\"
local state = 1;
if XGUIEng.IsButton(wID) == 1 then
state = 7;
end
if coord[3] == 0 then
SetIcon(wID,coord);
elseif coord[3] == 1 then
SetIcon(wID,coord);
elseif coord[3] == 2 then
local screenSize = {GUI.GetScreenSize()};
local sizeBase = {}
if file == nil then
file = "icons.png";
sizeBase[1] = 2000;
sizeBase[2] = 1140;
end
if coord[1] == -1 and coord[2] == -1 then
XGUIEng.SetMaterialAlpha(wID,state, 0);
else
XGUIEng.SetMaterialAlpha(wID,state, 255);
local u0 = (coord[1] - 1) * (size * (sizeBase[1]/screenSize[1]));
local v0 = (coord[2] - 1) * (size * (sizeBase[2]/screenSize[2]));
local u1 = coord[1] * (size * (sizeBase[1]/screenSize[1]));
local v1 = coord[2] * (size * (sizeBase[2]/screenSize[2]));
XGUIEng.SetMaterialTexture(wID,state,path .. file);
XGUIEng.SetMaterialUV(widget,state,u0,v0,u1,v1);
end
end
end
Demo-Map
<nicht vorhanden>
|