NPC verwandelt sich in Leibeigenen
» Siedler Map Source Forum » Siedler DEdK Script Forum » NPC verwandelt sich in Leibeigenen
Seiten: 1
Messoras
|
#1 25.09.2017 00:10 Beiträge: 84 |
NPC verwandelt sich in Leibeigenen
Hallo zusammen, ich habe nach einiger Zeit doch mal wieder zu Siedler 5 zurück gefunden und skripte auch schon wieder eifrig.
Dabei habe ich folgendes Problem:
Ich lasse einen Sägewerker aus dem Sägewerk kommen, der als NPC dient. Er kommt ganz normal heraus, doch sobald er stehen bleibt und untätig (also die Tasklist auf Idle gesetzt) wird, verwandelt er sich auf einmal in einen Leibeigenen.
Sobald er anfängt wieder irgendwo hin zu laufen oder ähnliches, wird er wieder zum Sägewerker. Ich habe den Verdacht, dass die Tasklist nicht 100% kompatibel ist.
Hier ist mein Code:
Erstmal die Funktionen, die ich mir zur Hilfe gebastelt habe (Wiederverwertung ftw):
function CreateCustomNPC(_name,_trigger,_callback) -- callback prüfen assert(type(_callback)=="function","CustomNPC: Falsche oder keine Callbackfunktion. Funktion erlaubt") -- name prüfen assert(type(_name)=="string","CustomNPC: Falscher oder kein Name. String erlaubt") -- trigger prüfen assert(type(_trigger)=="string" or type(_trigger)=="table" or type(_trigger)=="function", "CustomNPC: Falscher oder kein Trigger. String, Funktion oder Table erlaubt") -- NPC erstellen ( Ausrufezeichen ) local npc = { name = _name, callback = _callback } CreateNPC(npc) -- Implementierung des Triggers ( Entity/Entities oder Funktion ) TriggerNPCJob = function(_nameloc, _triggerloc, _callbackloc, _npcloc) if type(_triggerloc) == "table" then for i = 1, _triggerloc.n do if IsNear(_triggerloc[i],_nameloc,300) then _callbackloc() DestroyNPC(_npcloc) return true end end elseif type(_triggerloc) == "string" then if IsNear(_triggerloc,_nameloc,300) then _callbackloc() DestroyNPC(_npcloc) return true end elseif type(_triggerloc) == "function" then if _triggerloc() then _callbackloc() DestroyNPC(_npcloc) return true end elseif not _triggerloc then Message("Trigger is nil") return true end end StartSimpleJob("TriggerNPCJob",_name,_trigger,_callback,npc) end function GhostMove(_unit, _target) -- unit prüfen assert(type(_unit)=="string","CustomNPC: Falscher oder kein Einheitenname. String erlaubt.") -- target prüfen assert(type(_target)=="string","CustomNPC: Falscher oder kein Zielname. String erlaubt.") -- Blocking deaktivieren Logic.SetTaskList(GetID(_unit), TaskLists.TL_LEAVE_KEEP) local p = GetPosition(_target) -- Zielposition überschreiben Logic.MoveEntity(GetID(_unit), p.X, p.Y) -- Blocking wieder aktivieren StartSimpleJob("ArrivedJob",_unit,_target) end function NewNPCFromHouse(_npcName, _entityType, _playerID, _housePos, _targetPos) -- npcName prüfen assert(type(_npcName)=="string","CustomNPC: Falscher oder kein NPCname. String erlaubt.") -- entityType prüfen assert(type(_entityType)=="number","CustomNPC: Falscher oder kein Zielname. EntityType ( -> Nummer ) erlaubt.") -- playerID prüfen assert(type(_playerID)=="number","CustomNPC: Falsche oder keine PlayerID. Number erlaubt.") -- housePos prüfen assert(type(_housePos)=="string","CustomNPC: Falscher oder kein Gebäudename. String erlaubt.") -- target prüfen assert(type(_targetPos)=="string","CustomNPC: Falscher oder kein Zielname. String erlaubt.") -- Entity erstellen local pos = GetPosition(_housePos) Logic.SetEntityName( Logic.CreateEntity( _entityType, pos.X, pos.Y, 0, _playerID),_npcName ) -- bewegen GhostMove(_npcName, _targetPos) end function ArrivedJob (_unit, _target) if IsNear(_unit,_target,50) then -- Blocking aktivieren und NPC abwarten lassen Logic.SetTaskList(GetID(_unit), TaskLists.TL_NPC_IDLE) return true end end
Und hier jetzt der Aufruf:
NewNPCFromHouse("sawyer_1",Entities.PU_Sawmillworker,2,"sawmill","sawyer_1_pos") CreateCustomNPC("sawyer_1","messoras_child",SawyerBriefing1)
Gibt's eventuell ein Problem mit der Untätigkeit eines Arbeiters?
Sprich: Darf ich
Logic.SetTaskList(GetID("sawyer_1"), TaskLists.TL_NPC_IDLE)
benutzen?
Genau das gleiche hat mit einer Prinzessin funktioniert!
Danke im Voraus.
LG,
Messoras
____________________
Six feet of earth make us all equal.
Spielt Siedler 5 online mit mir, dank des neuen Siedler 5 MP Projekts von Kimichura.
mcb
|
#2 25.09.2017 01:15 Beiträge: 1472 |
Das liegt wahrscheinlich an der Serf-TaskList. Normalerweise gebe ich einfach einen normalen Befehl, sobald das Entity am Ziel angekommen ist um genau das zu verhindern. Bei dem Sawmillworker könnte NPC_Idle helfen, ich hatte damit aber auch schon Probleme (irgendwann ist er aus Arbeitsplatzmangel zum DZ raus...)
Am einfachsten wäre wohl ein HiResJob der das jeden Tick neu setzt. Oder du nimmst einen AfraidSawmillworker und setzt einfach eine normale Idle-Animation (sollte funktionieren, die haben dasselbe Model).
Messoras
|
#3 25.09.2017 11:08 Beiträge: 84 |
Ich müsste also meine ArrivedJob Funktion in etwa wie folgt verändern:
function ArrivedJob (_unit, _target) if IsNear(_unit,_target,50) then -- Blocking aktivieren und NPC abwarten lassen Logic.SetTaskList(GetID(_unit), TaskLists.TL_NPC_IDLE) --Leibeigenen Bug fixen local entID = GetEntityID(_unit) local ent = S5Hook.GetEntityMem(entID) local idleanim = GetEntityType(entID).[idle_anim_oder_so?] SetInt(ent[31][0][4],idleanim) return true end end
Frage: Wie kriege ich die richtige Konstante für die Idle Animation der entsprechenden Einheit?
#EDIT:
Ich habe eben bemerkt, dass der Sägewerker auch, wenn ich diese Arrived Funktion benutze, um ihn in einem Haus verschwinden zu lassen, bevor er sich auflöst, kurz zum Leibeigenen wird:
function ArrivedJobDeath (_unit, _target) if IsNear(_unit,_target,50) then -- Unit entfernen DestroyEntity(_unit) return true end end
Außerdem hat er sich ein mal nicht in einen Leibeigenen verwandelt und stand ganz normal als Sägewerker herum, wie er es sollte.
LG,
Messoras
____________________
Six feet of earth make us all equal.
Spielt Siedler 5 online mit mir, dank des neuen Siedler 5 MP Projekts von Kimichura.
Dieser Beitrag wurde von Messoras am 25.09.2017 um 11:31 editiert.
mcb
|
#4 25.09.2017 11:52 Beiträge: 1472 |
Eine Liste der Animationen findest du hier (zusammen mit der ältesten Version der Animationsfunktionen) : http://www.siedler-maps.de/forum/Siedler-DEdK-Script-Forum/SCV2-19696.htm
Eine größere Funktion für Animationen ist hier bei: http://www.siedler-maps.de/for...Script-Forum/mcbEMan-21315.htm
Aber was du suchst ist wohl einfach:
S5Hook.GetEntityMem(GetID(id))[31][0][4]:SetInt(386)
Zum falschen Model: Das passiert wie gesagt nicht immer. Ich benutze immer einen HiRes-Job für solche Sachen, da hatte ich nie Probleme mit.
Messoras
|
#5 25.09.2017 12:48 Beiträge: 84 |
Für das aktuelle scheint das gut zu passen, aber ich würde meine Comfort Funktion gerne erweitern, so dass die Units automatisch gefixt werden, und das vlt ohne für 100 verschiedene Einheiten ints zu switchen.
Ich werde mich mal durch die erweiterte Animationsfunktion forsten und schauen, ob ich da was passendes finde.
LG,
Messoras
____________________
Six feet of earth make us all equal.
Spielt Siedler 5 online mit mir, dank des neuen Siedler 5 MP Projekts von Kimichura.
Messoras
|
#6 25.09.2017 13:12 Beiträge: 84 |
Ich denke ich kann diese Tabelle evtl nutzen, um den Fix allgemein zu machen.
Ich würde also meinen ArrivedJob wiefolgt ändern:
function ArrivedJob (_unit, _target) if IsNear(_unit,_target,50) then -- Blocking aktivieren und NPC abwarten lassen Logic.SetTaskList(GetID(_unit), TaskLists.TL_NPC_IDLE) --Leibeigenen Bug fixen local entID = GetEntityID(_unit) local ent = S5Hook.GetEntityMem(entID) local idleanim = animTable.GetEntityType(entID).idle1 SetInt(ent[31][0][4],idleanim) return true end end
Wobei dann natürlich das Problem wäre dem aus GetEntityType ermittelten int die richtige Konstante zuzuweisen, um die entsprechende Nummer aus der Tabelle zu finden.
Oder ich muss wirklich einen Switch für jede Nummer machen und sagen
local t = GetEntityType(entID) if t==PU_Miner then idleanim = animTable.PU_Miner.idle1 elseif t==PU_Sawmillworker then idleanim = animTable.PU_Sawmiller.idle1 ...
Und ich hab ganz vergessen, dass es in lua nichtmal ne Switch Funktion gibt q.q
LG,
Messoras
____________________
Six feet of earth make us all equal.
Spielt Siedler 5 online mit mir, dank des neuen Siedler 5 MP Projekts von Kimichura.
Peter-FS
|
#7 25.09.2017 13:57 Beiträge: 1086 |
Ich habe das so gelöst, dient nur als Anregung, keine fertige Funktion
if Logic.GetCurrentTaskList(id) ~= "TL_LEAVE_KEEP" then if Logic.IsLeader(id) == 1 then Logic.SetTaskList(id, TaskLists.TL_MILITARY_IDLE) elseif Logic.GetEntityTypeName(Logic.GetEntityType(id))=="PU_Thief" then Logic.SetTaskList(id, TaskLists.TL_THIEF_IDLE) elseif Logic.GetEntityTypeName(Logic.GetEntityType(id))=="CU_EngineerIdle" then Logic.SetTaskList(id, TaskLists.TL_ENGINEER_IDLE) elseif Logic.IsSettler(id) == 1 then Logic.SetTaskList(id, TaskLists.TL_NPC_IDLE) else Logic.SetTaskList(id, TaskLists.TL_TRAIN2_TAVERN1) end
____________________
Man muss nicht alles wissen, man muss nur wissen wo es steht!
mcb
|
#8 25.09.2017 17:39 Beiträge: 1472 |
Die Tabelle ist so aufgebaut, das du sie aus dem Lua-Script heraus nutzen kannst. Am einfachsten währe wohl:
local anim = animTable[Logic.GetEntityTypeName(Logic.GetEntityType(GetID(id)))].idle1 assert(anim)
(Du müstest noch die Zeile mit dem SetInt fixen, die funktioniert so nicht )
PS: Das was in Lua einem switch am nächsten kommt ist wohl das hier:
local foo = 5 local t = {[1] = function() foo = 3 end, [5] = function() foo = foo + 2 end, } t[someinput]()
Edit: Hatte ein Logic.GetEntityTypeName vergessen
Dieser Beitrag wurde von mcb am 25.09.2017 um 17:56 editiert.
Messoras
|
#9 27.09.2017 08:30 Beiträge: 84 |
Sooo, danke für eure Beiträge. Ich werde das ganze jetzt mal so testen:
function AnimationJob (id,anim) if IsAlive(GetID(id)) and Logic.GetCurrentTaskList(GetID(id))==TaskLists.TL_NPC_IDLE then S5Hook.GetEntityMem(GetID(id))[31][0][4]:SetInt(anim) else return true end end function ArrivedJobDeath (_unit, _target) if IsNear(_unit,_target,50) then -- Unit entfernen DestroyEntity(_unit) return true end end
#EDIT: Scheint zu funktionieren, allerdings wird der AnimationJob immer sehr schnell beendet. Meist schon einen Tick nachdem der NPC stehen bleibt.
LG,
Messoras
____________________
Six feet of earth make us all equal.
Spielt Siedler 5 online mit mir, dank des neuen Siedler 5 MP Projekts von Kimichura.
Dieser Beitrag wurde von Messoras am 27.09.2017 um 10:31 editiert.
mcb
|
#10 27.09.2017 19:28 Beiträge: 1472 |
Du musst die Animation auch nur ein mal setzen. Die Comfortfunktion bei mir im Script benutze ich zum animieren von Heldenfähigkeiten, dabei muss ich natürlich neue Befehle jeden Tick wieder überschreiben
Seiten: 1