Merge branch 'fixes' into main/gingo-test
[ryzomcore.git] / ryzom / common / data_common / r2 / r2_logic.lua
blobd50a15faf0cfde96b3a4631efb8f925914d0a903
2 --
3 --
5 Logic = {}
7 Logic.Activities = {"Follow Route", "Patrol", "Repeat Road", "Deploy", "Wander", "Rest In Zone", "Feed In Zone", "Hunt In Zone", "Guard Zone", "Stand Still", "Stand On Start Point", "Go To Start Point"}
8 Logic.TimeLimits = {"No Limit", "Until", "Few Sec", "Few Min", "Chat", "Season", "Day", "Month"}
9 Logic.Seasons = {"Spring", "Summer", "Autumn", "Winter"}
10 Logic.Days = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
11 Logic.Months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
12 Logic.ScriptActions ={"Sit Down", "Stand Up", "Go To Step", "Set Activity", "Stop Actions", "Start Mission"}
14 Logic.EventModes ={"Once Only", "Repeating"}
15 Logic.EventTypes ={"Time", "Place", "Entity or Group", "State Machine", "Counter"}
16 Logic.ConditionTypes ={
17 {},
18 {"Any player in zone", "All players in zone", "No players in zone", "Some players in zone"},
19 {"At Destination", "Enters State", "Leaves State", "Activity Is", "Die", "Is Attacked"},
20 {},
21 {"v0_changed", "v3_changed", "Equals", "Lesser", "Greater", ""},
24 Logic.ChatTypes = {"None", "Repeating", "Non Repeating", "Continue"}
25 Logic.InteractionTypes = {"Give", "Say"}
27 Logic.Name = "Activity"
28 Logic.Description = "A feature for describing activities sequences"
33 Logic.Components = {}
38 -- ACTION -------------------
39 Logic.Components.LogicEntityAction =
41 BaseClass ="BaseClass",
42 Name = "LogicEntityAction",
43 DisplayerProperties = "R2::CDisplayerLua",
44 DisplayerPropertiesParams = "logicEntityActionPropertySheetDisplayer",
45 Prop =
47 {Name ="Name", Type ="String"},
48 {Name ="Event", Type ="EventType"},
49 {Name ="Actions", Type ="Table"}, -- "ActionStep" list
50 {Name ="Conditions", Type ="Table"}, -- "ConditionStep" list
53 getName = function(this)
55 local logicEntity = this.Parent.Parent.Parent
56 assert(logicEntity)
58 if logicEntity:isGrouped() then
59 logicEntity = logicEntity.ParentInstance
60 end
62 local coloredName = (logicEntity.InstanceId == r2.events.filteredLogicEntityId)
64 local eventType = r2.events.keyWordsColor .. i18n.get("uiR2EdEventTxtPreEvent"):toUtf8() .. " "
66 if coloredName then
67 eventType = eventType .. r2.events.filterWordColor
68 else
69 eventType = eventType .. r2.events.entityWordColor
70 end
71 local name = "No name"
72 if logicEntity.getName then
73 name = logicEntity:getName()
74 elseif logicEntity.Name then
75 name = logicEntity.Name
76 end
77 eventType = eventType .. name .. " "
78 eventType = eventType .. r2.events.communWordsColor
80 eventType = eventType ..r2.getLogicAttribute(logicEntity.Class, "Events", this.Event.Type).text
82 if this.Event.Value~="" then
83 local instance = r2:getInstanceFromId(this.Event.Value)
84 assert(instance)
86 eventType = eventType .. " " .. instance:getShortName()
87 end
90 if this.Event.ValueString and this.Event.ValueString ~= "" then
91 if string.gfind(eventType, "%%1")() then
92 eventType = string.gsub(eventType, "%%1", "'"..tostring(this.Event.ValueString).."'")
93 else
94 eventType = eventType .. " '" .. tostring(this.Event.ValueString).. "'"
95 end
96 end
98 eventType = eventType .. ", "
101 -- conditions
102 local conditionsList = ""
103 for i=0, this.Conditions.Size-1 do
104 local conditionInst = this.Conditions[i]
106 if conditionInst.Entity~="" and conditionInst.Condition.Type~="" then
108 conditionsList = conditionsList .. "\n" .. r2.events.keyWordsColor
109 ..string.upper(i18n.get("uiR2EdEventTxtPreCondition"):toUtf8()).." "
110 .. r2.events.communWordsColor
112 local conditionLogicEntity = r2:getInstanceFromId(tostring(conditionInst.Entity))
113 assert(conditionLogicEntity)
115 coloredName = (conditionLogicEntity.InstanceId == r2.events.filteredLogicEntityId)
116 if coloredName then
117 conditionsList = conditionsList .. r2.events.filterWordColor
118 else
119 conditionsList = conditionsList .. r2.events.entityWordColor
121 conditionsList = conditionsList .. conditionLogicEntity.Name .. " "
122 conditionsList = conditionsList .. r2.events.communWordsColor
124 conditionsList = conditionsList ..r2.getLogicAttribute(conditionLogicEntity.Class, "Conditions", conditionInst.Condition.Type).text
126 if conditionInst.Condition.Value~="" then
127 local instance = r2:getInstanceFromId(conditionInst.Condition.Value)
128 assert(instance)
129 conditionsList = conditionsList .. " '" .. instance:getShortName() .."'"
132 conditionsList = conditionsList .. ", "
136 -- actions
137 local actionsList = ""
138 for i=0, this.Actions.Size-1 do
139 local actionInst = this.Actions[i]
141 if actionInst.Entity~="" and actionInst.Action.Type~="" then
143 actionsList = actionsList .. "\n" .. r2.events.keyWordsColor
144 ..string.upper(i18n.get("uiR2EdEventTxtPreActions"):toUtf8()).." "
145 .. r2.events.communWordsColor
147 local actionLogicEntity = r2:getInstanceFromId(tostring(actionInst.Entity))
148 assert(actionLogicEntity)
150 coloredName = (actionLogicEntity.InstanceId == r2.events.filteredLogicEntityId)
151 if coloredName then
152 actionsList = actionsList .. r2.events.filterWordColor
153 else
154 actionsList = actionsList .. r2.events.entityWordColor
156 local name = "No name"
157 if actionLogicEntity.getName then
158 name = actionLogicEntity:getName()
159 elseif actionLogicEntity.Name then
160 name = actionLogicEntity.Name
162 actionsList = actionsList .. name .. " "
163 actionsList = actionsList .. r2.events.communWordsColor
165 actionsList = actionsList ..r2.getLogicAttribute(actionLogicEntity.Class, "ApplicableActions", actionInst.Action.Type).text
166 if actionInst.Action.Value~="" then
167 local instance = r2:getInstanceFromId(actionInst.Action.Value)
168 assert(instance)
169 actionsList = actionsList .. " '" .. instance:getShortName() .. "'"
172 if actionInst.Action.ValueString and actionInst.Action.ValueString ~= "" then
174 if string.gfind(actionsList, "%%1")() then
175 actionsList = string.gsub(actionsList, "%%1", "'"..tostring(actionInst.Action.ValueString).."'")
176 else
177 actionsList = actionsList .. " '" .. tostring(actionInst.Action.ValueString).. "'"
181 if i~=this.Actions.Size-1 then
182 actionsList = actionsList .. ","
183 else
184 actionsList = actionsList .. "."
189 if actionsList=="" then
190 actionsList = "\n..."
193 return eventType .. conditionsList .. actionsList --.. "\n"
194 end,
196 getLogicEntityParent = function(this)
198 local logicEntity = this.Parent.Parent.Parent
199 if logicEntity:isGrouped() then logicEntity = logicEntity.Parent.Parent end
201 return logicEntity
202 end,
204 -- The act of the event
205 getLogicAct = function(this)
207 local currentAct = r2:getCurrentAct()
208 local baseAct = r2.Scenario:getBaseAct()
209 local isBaseAct = false
210 local presentActs = {}
211 local isCurrentAct = false
212 local counter = 0
215 local entity = this:getLogicEntityParent()
216 if entity and entity.getParentAct then
217 local act = entity:getParentAct()
218 if act then
219 if act==currentAct then
220 isCurrentAct=true
221 elseif act==baseAct then
222 isBaseAct = true
223 else
224 presentActs[act.InstanceId] = act.InstanceId
225 counter = counter+1
231 local function verifyAct ( container)
233 local key, value = next(container, nil)
234 while key do
235 if value.Action and value.Action.Type == "Start Act" then
236 else
237 local entityId = value.Entity
238 local entity= r2:getInstanceFromId(entityId)
239 if entity and entity.getParentAct then
240 local act = entity:getParentAct()
241 if act then
242 if act==currentAct then
243 isCurrentAct=true
244 elseif act==baseAct then
245 isBaseAct = true
246 else
247 presentActs[act.InstanceId] = act.InstanceId
248 counter = counter+1
253 key, value = next(container, key)
257 verifyAct(this.Actions)
258 verifyAct(this.Conditions)
260 if counter>=2 or (counter==1 and isCurrentAct) then
261 return nil
262 elseif counter==1 and not isCurrentAct and isBaseAct then
263 local act = nil
264 for k, actId in pairs(presentActs) do
265 act = r2:getInstanceFromId(actId)
266 break
268 --inspect(act)
269 return act
270 else
271 --inspect(currentAct)
272 return currentAct
274 end,
279 ----------
280 -- called upon translation
281 getLogicActForTranslate = function(this)
282 local currentAct = this:getLogicEntityParent():getParentAct()
283 local baseAct = r2.Scenario:getBaseAct()
285 local entity = this.Event.Entity
286 if entity and entity.getParentAct then
287 local act = entity:getParentAct()
288 if currentAct == nil then
289 currentAct = act
290 elseif act ~= currentAct then
291 if currentAct == baseAct then
292 currentAct = act
293 elseif act == baseAct then
294 -- do nothing
295 else
296 return nil
303 local function verifyAct ( container)
304 local key, value = next(container, nil)
305 while key do
306 if value.Action and value.Action.Type == "Start Act" then
307 else
308 local entityId = value.Entity
309 local entity= r2:getInstanceFromId(entityId)
310 if entity and entity.getParentAct then
311 local act = entity:getParentAct()
312 if act then
313 if currentAct == nil then
314 currentAct = act
315 elseif act ~= currentAct then
316 if currentAct == baseAct then
317 currentAct = act
318 elseif act == baseAct then
319 -- do nothing
320 else return false
326 key, value = next(container, key)
328 return true
332 if not verifyAct(this.Actions) then return false end
333 if not verifyAct(this.Conditions) then return false end
334 return currentAct
335 end,
337 getLogicActInstanceId = function(this)
338 --local ok, act = pcall(Logic.Components.LogicEntityAction.getLogicAct, this)
339 local ok, act = pcall(Logic.Components.LogicEntityAction.getLogicActForTranslate, this)
340 if not ok or not act then
341 return r2.RefId("")
344 return act.InstanceId
345 end,
348 Logic.Components.EventType =
350 BaseClass ="BaseClass",
351 Name = "EventType",
352 DisplayerProperties = "R2::CDisplayerLua",
353 DisplayerPropertiesParams = "eventTypePropertySheetDisplayer",
354 Prop =
356 {Name ="Type", Type ="String"},
357 {Name ="Value", Type ="RefId"}, -- if type is end of activity/chat step/sequence, instance id
358 {Name ="ValueString", Type ="String", DefaultValue="", DefaultInBase=1}, -- if type is emit user event, sub timer...
363 local classActionStepVersion = 2
364 Logic.Components.ActionStep = {
365 BaseClass ="BaseClass",
366 Name = "ActionStep",
367 Version = classActionStepVersion,
368 DisplayerProperties = "R2::CDisplayerLua",
369 DisplayerPropertiesParams = "actionStepPropertySheetDisplayer",
370 Prop =
372 {Name ="Entity", Type ="RefId"}, -- entity target id
373 {Name ="Action", Type ="ActionType"} -- sequence id
376 updateVersion = function(this, scenarioValue, currentValue )
378 local patchValue = scenarioValue
379 if patchValue < 1 then
380 local invalidActions = {}
381 invalidActions["desactivate"] = "deactivate"
382 invalidActions["Desactivate"] = "deactivate"
383 r2.updateLogicActions(this, invalidActions, "BanditCamp")
384 patchValue = 1
387 if patchValue < 2 then
389 local action = this.Action
390 if action.Type == "Add 10 Seconds" then
391 r2.requestSetNode(action.InstanceId, "Type", "add seconds")
392 r2.requestInsertNode(action.InstanceId, "", -1, "ValueString", "10")
395 if action.Type == "Sub 10 seconds" then
396 r2.requestSetNode(action.InstanceId, "Type", "sub seconds")
397 r2.requestInsertNode(action.InstanceId, "", -1, "ValueString", "10")
399 if action.Type == "Add 1 minute" then
400 r2.requestSetNode(action.InstanceId, "Type", "add seconds")
401 r2.requestInsertNode(action.InstanceId, "", -1, "ValueString", "60")
404 if action.Type == "Sub 1 minute" then
405 r2.requestSetNode(action.InstanceId, "Type", "sub seconds")
406 r2.requestInsertNode(action.InstanceId, "", -1, "ValueString", "60")
409 patchValue = 2
412 if patchValue == currentValue then return true end
413 return false
414 end,
418 Logic.Components.ActionType =
420 BaseClass ="BaseClass",
421 Name = "ActionType",
422 DisplayerProperties = "R2::CDisplayerLua",
423 DisplayerPropertiesParams = "actionTypePropertySheetDisplayer",
424 Prop =
426 {Name ="Type", Type ="String"},
427 {Name ="Value", Type ="RefId"}, -- if type is begin of activity/chat sequence, instance id
428 {Name ="ValueString", Type ="String", DefaultValue="", DefaultInBase=1}, -- if type is emit user event, sub timer...
434 Logic.Components.ConditionStep =
436 BaseClass ="BaseClass",
437 Name = "ConditionStep",
438 DisplayerProperties = "R2::CDisplayerLua",
439 DisplayerPropertiesParams = "conditionStepPropertySheetDisplayer",
440 Prop =
442 {Name ="Entity", Type ="RefId"}, -- entity id
443 {Name ="Condition", Type ="ConditionType"}
448 Logic.Components.ConditionType =
450 BaseClass ="BaseClass",
451 Name = "ConditionType",
452 DisplayerProperties = "R2::CDisplayerLua",
453 DisplayerPropertiesParams = "conditionTypePropertySheetDisplayer",
454 Prop =
456 {Name ="Type", Type ="String"},
457 {Name ="Value", Type ="RefId"}, -- if type is being in activity/chat step/sequence, instance id
463 -- REACTION -----------------
465 Logic.Components.LogicEntityReaction =
467 BaseClass ="BaseClass",
468 Name = "LogicEntityReaction",
469 DisplayerProperties = "R2::CDisplayerLua",
470 DisplayerPropertiesParams = "logicEntityReactionPropertySheetDisplayer",
471 Prop =
473 {Name ="Name", Type ="String"},
474 {Name ="LogicEntityAction", Type ="String"}, -- id of associated LogicEntityAction
475 {Name ="ActionStep", Type ="String"}, -- id of associated ActionStep
479 Logic.Components.ChatAction=
481 BaseClass ="BaseClass",
482 Name ="ChatAction",
483 DisplayerProperties = "R2::CDisplayerLua",
484 DisplayerPropertiesParams = "chatActionPropertySheetDisplayer",
485 Prop =
487 {Name ="Who", Type ="RefId"},
488 {Name ="WhoNoEntity", Type ="String"},
489 {Name ="Says", Type ="String"},
490 {Name ="Emote", Type ="String"},
491 {Name ="Facing", Type ="RefId"},
492 -- {Name ="FacingNoEntity", Type ="String"},
496 Logic.Components.ChatStep = {
497 BaseClass ="BaseClass",
498 Name = "ChatStep",
499 DisplayerProperties = "R2::CDisplayerLua",
500 DisplayerPropertiesParams = "chatStepPropertySheetDisplayer",
501 Prop =
503 {Name ="Actions", Type ="Table"},
504 {Name ="Time", Type ="Number" },
505 {Name ="Name", Type ="String" }
508 getName = function(this)
510 -- after time
511 local minNb, secNb = r2.dialogs:calculMinSec(this.Time)
512 local time = ""
513 if minNb ~= 0 then
514 time = tostring(minNb)..i18n.get("uiR2EdShortMinutes"):toUtf8()
516 time = time.." " ..tostring(secNb)..i18n.get("uiR2EdShortSeconds"):toUtf8()
517 local afterTime = "(" ..i18n.get("uiR2EdAfter"):toUtf8().." ".. time..") "
519 -- says
520 local whoToWho = ""
521 local action = this.Actions[0]
522 local who = action.Who
523 if who=="" then who=action.WhoNoEntity end
524 if who and who ~= "" then
526 if r2:getInstanceFromId(who) then
527 who=r2:getInstanceFromId(who).Name
528 else
529 who = r2.dialogs.whoToWhoTranslation[who]
532 whoToWho = who .. " "
534 local facing = action.Facing
535 if facing~="" then
536 whoToWho = whoToWho ..i18n.get("uiR2EdSaysTo"):toUtf8().. " " .. r2:getInstanceFromId(facing).Name .. " "
539 local emote = action.Emote
540 if emote~="" and r2.dialogs.fromEmoteIdToName[emote] ~= nil then
541 whoToWho = whoToWho .."(" .. r2.dialogs.fromEmoteIdToName[emote] .. ") :"
545 return afterTime..whoToWho
547 end,
549 getShortName = function(this)
551 -- says
552 local saysWhat = ""
553 local action = this.Actions[0]
554 local who = action.Who
555 if who ~= "" or WhoNoEntity~="" then
556 who = r2:getInstanceFromId(who)
557 if who then
558 saysWhat = who.Name
559 elseif action.WhoNoEntity=="_System" then
560 saysWhat = i18n.get("uiR2EdSystem"):toUtf8()
561 elseif action.WhoNoEntity=="_DM" then
562 saysWhat = i18n.get("uiR2EdDonjonMaster"):toUtf8()
565 saysWhat = saysWhat .. " " ..i18n.get("uiR2EdSays"):toUtf8().. " "
567 local says = action.Says
568 if says ~= "" then
569 local inst=r2:getInstanceFromId(says)
570 if inst then
571 says = inst.Text
572 local uc_says = ucstring()
573 uc_says:fromUtf8(says)
574 uc_says = uc_says:substr(0, 4)
575 says = uc_says:toUtf8()
580 saysWhat = saysWhat .. says .. "..."
583 return saysWhat
585 end,
587 --------------------------------------------------------------------------------------------
588 -- from 'BaseClass'
589 getParentTreeNode = function(this)
590 end,
594 local classChatSequenceVersion = 1
595 Logic.Components.ChatSequence = {
596 PropertySheetHeader = r2.getDisplayButtonHeader("r2.dialogs:openEditor()", "uiR2EdEditDialogButton"),
597 BaseClass = "LogicEntity",
598 Name = "ChatSequence",
599 InEventUI = true,
600 Menu="ui:interface:r2ed_feature_menu",
601 Version = classChatSequenceVersion,
603 DisplayerProperties = "R2::CDisplayerLua",
604 DisplayerPropertiesParams = "chatSequencePropertySheetDisplayer",
606 DisplayerUI = "R2::CDisplayerLua",
607 DisplayerUIParams = "defaultUIDisplayer",
608 DisplayerVisual = "R2::CDisplayerVisualEntity",
610 Parameters = {},
611 ApplicableActions = {
612 "activate", "deactivate", "starts dialog", "stops dialog", "starts chat" , "continues dialog"
614 Events = {
615 "start of dialog", "end of dialog" ,
616 "start of chat", "end of chat",
617 "activation", "deactivation"
619 Conditions = {
620 "is not in dialog", "is in dialog", "is in chat"
622 TextContexts = {},
623 TextParameters = {},
624 LiveParameters = {},
627 Prop =
629 {Name = "Type", Type="String",DefaultValue = "None", Visible=false},
630 {Name ="Repeating", Type="Number" ,DefaultValue = "0", Visible=false},
631 {Name="Components",Type="Table"},
632 {Name="SubComponents", Type="Table"},
633 {Name="Name", Type="String", MaxNumChar="32"},
634 {Name="AutoStart", Type="Number", WidgetStyle="Boolean", DefaultValue="1", Visible=function(this) return this:mustDisplayAutostart() end},
635 {Name="Active", Type="Number", WidgetStyle="Boolean", DefaultValue = "1"},
639 mustDisplayAutostart = function(this)
640 if this.Class == "ProximityDialog" then
641 return false
643 return true
644 end,
646 -- it's a feature
647 getParentTreeNode = function(this)
648 return this:getFeatureParentTreeNode()
649 end,
651 onPostCreate = function(this)
652 --this:createGhostComponents()
653 if this.User.DisplayProp and this.User.DisplayProp == 1 then
654 r2:setSelectedInstanceId(this.InstanceId)
655 r2:showProperties(this)
656 this.User.DisplayProp = nil
659 end,
661 create = function()
663 --if r2:getLeftQuota() <= 0 then -- ??
664 -- r2:makeRoomMsg()
665 -- return
666 --end
668 local function posOk(x, y, z)
669 if r2.mustDisplayInfo("ChatSequence") == 1 then
670 r2.displayFeatureHelp("ChatSequence")
672 debugInfo(string.format("Validate creation of 'Dialog' at pos (%d, %d, %d)", x, y, z))
673 r2.dialogs:newSequenceInst(x, y, z)
675 local function posCancel()
676 debugInfo("Cancel choice 'Dialog' position")
677 end
679 local creature = r2.Translator.getDebugCreature("object_component_dialog.creature")
680 r2:choosePos(creature, posOk, posCancel, "createDialog")
681 end,
683 ---- get Name ------
684 getName = function(this)
686 local name = this.Name
687 if name == "" then
689 local index = r2.logicComponents:searchElementIndex(this)
690 if index >= 0 then
691 name = i18n.get("uiR2EDDialog"):toUtf8() .. index
695 return name
696 end,
698 ---- get Name ------
699 getShortName = function(this)
701 return this:getName()
702 end,
704 ---------------------------------------------------------------------------------------------------------
706 editDialogs = function(this)
707 r2.dialogs:openEditor()
708 end,
710 getAvailableCommands = function(this, dest)
711 r2.Classes.LogicEntity.getAvailableCommands(this, dest)
712 table.insert(dest, this:buildCommand(this.editDialogs, "edit_dialogs", "uiR2EDEditDialogs", "r2ed_edit_dialog.tga", true))
713 this:getAvailableDisplayModeCommands(dest)
714 end,
716 initEventValuesMenu = function(this, menu, categoryEvent)
717 for ev=0,menu:getNumLine()-1 do
719 local eventType = tostring(menu:getLineId(ev))
721 if r2.events.eventTypeWithValue[eventType] == "Number" then
722 menu:addSubMenu(ev)
723 local subMenu = menu:getSubMenu(ev)
724 local func = ""
725 for i=0, 9 do
726 local uc_name = ucstring()
727 uc_name:fromUtf8( tostring(i) )
728 func = "r2.events:setEventValue('','" .. categoryEvent .."','".. tostring(i).."')"
729 subMenu:addLine(uc_name, "lua", func, tostring(i))
732 elseif r2.events.eventTypeWithValue[eventType]=="ChatStep" then
734 menu:addSubMenu(ev)
735 local subMenu = menu:getSubMenu(ev)
737 for c=0, this.Components.Size-1 do
738 local chat = this.Components[c]
739 local uc_name = ucstring()
740 uc_name:fromUtf8(chat:getShortName())
741 subMenu:addLine(uc_name, "lua",
742 "r2.events:setEventValue('".. chat.InstanceId .."','" .. categoryEvent .. "')", chat.InstanceId)
745 if this.Components.Size==0 then
746 subMenu:addLine(i18n.get("uiR2EdNoSelelection"), "", "", "")
750 end,
752 getLogicAction = function(this, context, action)
753 return r2.Translator.getDialogLogicAction(this, context, action)
754 end,
755 getLogicEvent = function(this, context, event)
756 return r2.Translator.getDialogLogicEvent(this, context, event)
757 end,
758 getLogicCondition = function(this, context, condition)
759 return r2.Translator.getDialogLogicCondition(this, context, condition)
760 end,
762 pretranslate = function(this, context)
763 r2.Translator.createAiGroup(this, context)
764 end,
766 translate = function(this, context)
767 r2.Translator.translateFeatureActivation(this, context)
768 r2.Translator.translateDialog( this, context)
769 end,
771 updateVersion = function(this, scenarioValue, currentValue )
772 local patchValue = scenarioValue
773 if patchValue < 1 then
774 local subComponents = {}
775 r2.requestInsertNode(this.InstanceId, "", -1, "SubComponents", subComponents)
776 r2.requestInsertNode(this.InstanceId, "", -1, "AutoStart", this.Active)
777 r2.requestSetNode(this.InstanceId, "Active", 1)
778 r2.requestSetNode(this.InstanceId, "Base", r2.Translator.getDebugBase("palette.entities.botobjects.dialog"))
779 patchValue = 1
782 if patchValue == currentValue then return true end
783 return false
784 end,
786 initLogicEntitiesInstancesMenu = function(this, subMenu, calledFunction)
788 local entitiesTable = r2.Scenario:getAllInstancesByType(this.Name)
789 for key, entity in pairs(entitiesTable) do
790 local uc_name = ucstring()
791 uc_name:fromUtf8(entity.Name)
792 subMenu:addLine(uc_name, "lua", calledFunction.."('".. entity.InstanceId .."')", entity.InstanceId)
795 if table.getn(entitiesTable)==0 then
796 subMenu:addLine(i18n.get("uiR2EdNoSelelection"), "", "", "")
803 local ActivityStepVersion = 1
804 Logic.Components.ActivityStep = {
805 BaseClass ="BaseClass",
806 Name ="ActivityStep",
807 Version = ActivityStepVersion,
808 BuildPropertySheet = true,
809 Menu ="ui:interface:r2ed_feature_menu",
811 BuildPropertySheet = false,
812 DisplayerVisualParams =
814 Look = r2.PrimRender.GroupLook,
815 ArrayName = "Components"
817 DisplayerProperties = "R2::CDisplayerLua",
818 DisplayerPropertiesParams = "activityStepPropertySheetDisplayer",
820 Prop =
822 {Name="Activity", Type="String"},
823 {Name="ActivityZoneId",Type="RefId",Category="ActivityStep"},
824 {Name="TimeLimit",Type="String",Category="ActivityStep"},
825 {Name="TimeLimitValue", Type="String",Category="ActivityStep",Category="ActivityStep"},
826 {Name="RoadCountLimit", Type="String",Category="ActivityStep",Category="ActivityStep", DefaultInBase = 1, DefaultValue = "0"},
827 {Name="Chat",Type="RefId"},
828 {Name = "Type", Type="String",DefaultValue = "None"}, --TEMP TEMP TEMP
829 {Name="EventsIds",Type="Table"},
830 {Name="Name", Type="String", MaxNumChar="32"}
832 -- get sequencable parent for this activity step
833 getSequencableParent = function(this)
834 local currParent = this.Parent
835 while currParent do
836 if currParent.InstanceId and currParent:isSequencable() then
837 return currParent
839 currParent = currParent.Parent
841 return nil
842 end,
843 getVerbLookupString = function(this)
844 local seqParent = this:getSequencableParent()
845 if seqParent then
846 return seqParent:getActivityVerbLookupName(this.Activity)
847 else
848 return this.Activity
849 end
850 end,
851 -- do lookup from the verb lookup string used to know the display name, and button texture
852 doLookupFromVerb = function(this, lookupTable)
853 local lookupString = this:getVerbLookupString()
854 -- activity type
855 local value = lookupTable[lookupString]
856 if not value then
857 debugInfo(colorTag(255,0,0).."The activity '".. lookupString .."' is not properly registred")
858 return nil
860 return value
861 end,
862 -- get texture for the button displayed in the mini activity view
863 getMiniButtonTexture = function(this)
864 local result = this:doLookupFromVerb(r2.miniActivities.activityTextures)
865 if result then return result end
866 return "brick_default.tga"
867 end,
868 -- get the verb for this activity (rest, feed, patrol etc...)
869 getVerb = function(this)
870 local result = this:doLookupFromVerb(r2.activities.activityTypeTranslation)
871 if result then result = result.trans end
872 if result then return result end
873 return ucstring("Activity not registered : " .. lookupString)
874 end,
875 -- element name
876 getName = function(this)
877 local activityType = this:getVerb() .. " "
878 if this.ActivityZoneId~= "" then
879 local place = r2:getInstanceFromId(tostring(this.ActivityZoneId))
880 if place~=nil then
881 activityType = activityType.. place.Name .." "
882 end
885 -- activity time
886 local activityTime = ""
887 if this.TimeLimit == "Few Sec" then
889 local hourNb, minNb, secNb = r2.logicComponents:calculHourMinSec(tonumber(this.TimeLimitValue))
891 local timeLimitText = i18n.get("uiR2EdFor"):toUtf8() .. " "
892 if hourNb ~= 0 then timeLimitText = timeLimitText .. hourNb .. i18n.get("uiR2EdShortHours"):toUtf8() .. " " end
893 if minNb ~= 0 then timeLimitText = timeLimitText .. minNb .. i18n.get("uiR2EdShortMinutes"):toUtf8() .. " " end
894 timeLimitText = timeLimitText .. secNb .. i18n.get("uiR2EdShortSeconds"):toUtf8()
896 activityTime = timeLimitText
898 elseif r2.activities.timeLimitsTranslation[this.TimeLimit] ~= nil then
899 activityTime = string.lower(r2.activities.timeLimitsTranslation[this.TimeLimit])
902 return activityType..activityTime
903 end,
905 -- element name
906 getShortName = function(this)
908 -- activity type
909 local activityType = this:getVerb()
910 if this.ActivityZoneId~= "" then
911 local place = r2:getInstanceFromId(tostring(this.ActivityZoneId))
912 if place~=nil then
913 activityType = activityType.. " " .. place.Name
914 end
917 return activityType
918 end,
920 updateVersion = function(this, scenarioValue, currentValue )
921 local patchValue = scenarioValue
923 if patchValue < 1 then
924 local activity = this.Activity
925 if (activity and activity == "Inactive") then
926 r2.requestSetNode(this.InstanceId, "Activity", "Stand Still")
928 local name = this.Name
930 patchValue = 1
932 if patchValue == currentValue then return true end
933 return false
939 Logic.Components.ActivitySequence = {
940 BaseClass="BaseClass",
941 Name="ActivitySequence",
942 BuildPropertySheet = true,
943 Menu ="ui:interface:r2ed_feature_menu",
945 --DisplayerUI = "R2::CDisplayerLua",
946 --DisplayerUIParams = "defaultUIDisplayer",
947 BuildPropertySheet = false,
948 DisplayerVisual = "R2::CDisplayerVisualActivitySequence",
949 DisplayerProperties = "R2::CDisplayerLua",
950 DisplayerPropertiesParams = "activitySequencePropertySheetDisplayer",
952 Prop =
954 --{Name ="InstanceId", Type ="String"},
955 {Name ="Repeating", Type ="Number" , DefaultValue = "1"},
956 {Name ="Components", Type ="Table"},
957 {Name ="Name", Type ="String"}
960 ---- get Name ------
961 getName = function(this)
963 local name = this.Name
964 if name == "" then
966 local index = r2.logicComponents:searchElementIndex(this)
968 if index >= 0 then
969 name = i18n.get("uiR2EdSeq"):toUtf8() .. index
973 return name
974 end,
976 ---- get Name ------
977 getShortName = function(this)
979 return this:getName()
980 end,
982 -- get ActiveLogicEntity parent
983 getActiveLogicEntityParent = function(this)
985 -- ActiveLogicEntity.Behavior.Activities
986 local activeLogicEntity = this.Parent.Parent.Parent
988 -- NpcGrpFeature.Components
989 --if activeLogicEntity:isGrouped() then activeLogicEntity = activeLogicEntity.Parent.Parent end
991 return activeLogicEntity
992 end,
997 --this function must be called when we delete a ChatAction,
998 --to unregister the text
999 onDeleteChatAction = function(chatAction)
1000 if chatAction.User.DeleteInProgress == true then return end
1001 chatAction.User.DeleteInProgress = true
1002 if chatAction.Says ~= nil and chatAction.Says ~= ""
1003 then
1005 debugInfo("onDeleteChatAction")
1006 r2.unregisterTextFromId(chatAction.Says)
1010 --counts the states created, to ensure states names uniqueness
1012 --timer used to time the sequences steps
1013 Logic.activityStepTimer = "t0"
1014 Logic.activityStepTimerId = 0
1015 --timer used to time the chat steps
1016 Logic.chatTimer = "t1"
1017 Logic.chatTimerId = 1
1018 --timer used inside activities
1019 Logic.activityInternalTimer = "t2"
1020 Logic.activityInternalTimerId = 2
1022 --variable used to know which action of the current chat sequence
1023 --must be played
1024 Logic.chatStepVar = "v1"
1025 --variable used to know which chat sequence is currently played
1026 Logic.chatSequenceVar = "v0"
1027 --variable used to know which activity sequence is currently played
1028 Logic.activityStepVar = "v2"
1029 --variable used to know which interrupt action must be executed
1030 Logic.triggerEventVar = "v3"
1032 Logic.EndOfActivitySequenceEvent = 9
1033 Logic.EndOfChatSequenceEvent = 8
1035 --switch_action which hold all chat sequences
1036 Logic.DialogAction = nil
1037 --switch action holding chat sequences transitions
1038 Logic.DialogAction2 = nil
1040 --switch_action which hold all sequence steps
1041 Logic.SequenceAction = nil
1042 Logic.ActionStepCounter =0
1043 Logic.ChatSequenceCounter = 0
1044 --used to know the names of all the states generated
1045 --to translate this activity
1046 Logic.StatesByName = ""
1048 --timer_triggered event, triggered
1049 --each time we must enter a new chat step
1050 Logic.DialogEvent = nil
1052 Logic.DialogEvent2 = nil
1054 --timer_triggered event, triggered
1055 --each time we must enter a new sequence step
1056 Logic.SequenceEvent = nil
1058 --hold the states used in the current activity.
1059 --all the states are created at the start of the translation,
1060 --before translating the events and actions.
1061 Logic.States = {}
1063 --hold the states used in all the activities
1064 --of the group
1065 Logic.ActivitiesStates ={}
1067 --the activity which is currently being translated.
1068 Logic.CurrentActivity = nil
1070 ----------------------------------------------------
1071 --to be called once for each sequence of each group
1072 --complete the AiActivity field of the first state of this sequence
1073 --and create the actions to go to the first step
1074 Logic.initGroupActivitiesTranslation = function(context, hlComponent, sequence, first, activityIndex, aiActivity, rtGrp)
1075 assert(context and hlComponent and sequence and activityIndex and aiActivity and rtGrp)
1076 --get the states of this activity
1078 local activityStates = Logic.ActivitiesStates[ tostring(sequence.InstanceId) ]
1079 assert(sequence.Class == "ActivitySequence")
1080 if not activityStates then
1082 if hlComponent then
1083 printWarning("Error while translating '" .. hlComponent.Name .. "' activities in sequence " .. sequence.Name)
1084 -- pretranslate sequence.InstanceId errors instanceId not added in currentAct.ActivitiesId ?
1085 return nil
1086 end
1088 --get the initial state of this activity
1089 local aiState = activityStates[sequence.InstanceId][1]
1090 Logic.StatesByName = ""
1091 for k, v in pairs(activityStates)
1093 if v.Class ~= "RtAiState"
1094 then
1095 local k1, v1 = next( v, nil)
1096 while k1 do
1097 Logic.StatesByName = r2.Utils.concat(Logic.StatesByName, v1.Name)
1098 k1, v1 = next(v, k1)
1100 else
1101 Logic.StatesByName = r2.Utils.concat(Logic.StatesByName, v.Name)
1104 aiState.AiActivity = aiActivity
1105 assert(aiState.AiActivity)
1106 local event = r2.Translator.createEvent("start_of_state", aiState.Name, rtGrp.Name)
1107 -- local event = r2.Translator.createEvent("group_spawned", aiState.Name, rtGrp.Name)
1108 table.insert(context.RtAct.Events, event)
1109 if first == true
1110 then
1111 table.insert(aiState.Children, rtGrp.Id)
1114 local speed = ""
1116 if hlComponent.Speed and hlComponent.Speed == "run" then speed = "()addProfileParameter(\"running\");\n" end
1118 local code = "currentActivitySequenceVar = " .. tostring(activityIndex -1 ) ..";\n"
1119 .. "oldActivitySequenceVar = currentActivitySequenceVar;\n"
1120 .. "RoadCountLimit=0;\n"
1121 .. "oldActivityStepVar = -1;\n"
1122 .. "oldActivityStepVar2 = 0;\n"
1123 .. Logic.activityStepVar .." = 0;\n"
1124 .. speed
1125 .."alive = 0;\n"
1126 .."(alive)isAlived();\n"
1127 .. "if (alive == 1)\n{\n"
1128 .. "\t()setTimer(30, " .. Logic.activityStepTimerId .. ");\n"
1129 .. "\tinit = 1;\n"
1130 .. "}\n"
1133 -- Fauna activities
1136 local action = r2.Translator.createAction("code", code)
1137 action.Name = "startActivitySequence"
1139 table.insert(context.RtAct.Actions, action)
1140 table.insert(event.ActionsId, action.Id)
1145 local event = r2.Translator.createEvent("group_spawned", aiState.Name, rtGrp.Name)
1146 local action = r2.Translator.createAction("code", "if (init != 1)\n{\n\t()setTimer(30, " .. Logic.activityStepTimerId .. ");\n}\n")
1147 table.insert(context.RtAct.Events, event)
1148 table.insert(context.RtAct.Actions, action)
1149 table.insert(event.ActionsId, action.Id)
1153 local leader = hlComponent
1155 if hlComponent:isKindOf("NpcGrpFeature") then
1156 if hlComponent.Components.Size ~= 0 then
1157 leader = hlComponent.Components[0]
1158 else
1159 leader = nil
1164 --insert an activity step at the specified position
1165 Logic.insertActivityStep = function(sequence, step, pos)
1166 local n = table.getn(sequence.Components)
1167 if n < pos
1168 then
1169 table.insert(sequence.Components, step)
1170 else
1171 table.insert(sequence.Components, pos, step)
1175 --insert a chat step at the specified position
1176 Logic.insertChatStep = function(chatSequence, chatStep, pos)
1177 local n = table.getn(chatSequence.Components)
1178 if n < pos
1179 then
1180 table.insert(chatSequence.Components, chatStep)
1181 else
1182 table.insert(chatSequence.Components, pos)
1187 Logic.createInteraction = function(action, parameter)
1188 local index = Logic.find(Logic.InteractionTypes, action)
1189 local interaction
1191 if index == nil or parameter == nil
1192 then
1193 -- debugInfo(colorTag(255,0,0).."unknown interaction : " .. action .." !")
1194 return nil
1197 interaction = r2.newComponent("Interaction")
1198 interaction.Type = action
1199 interaction.Parameter = parameter
1200 return interaction
1203 Logic.createActivityStep = function(activity, timeLimit, zoneId, time)
1204 local activityStep = nil
1206 if activity == nil or timeLimit == nil
1207 then
1208 return nil
1211 --checking activity type and time limit type
1212 if Logic.find(Logic.Activities, activity)~= nil and Logic.find(Logic.TimeLimits, timeLimit)~= nil
1213 then
1214 --checking activity parameter
1215 if ( (activity ~= "Stand Still") and (activity ~= "Inactive") and (zoneId == nil) )
1216 then
1217 --this activity need a zone, and no zone id is given
1218 -- debugInfo(colorTag(255,0,0).."activity <" .. activity .."> need a zone id!")
1219 return nil
1222 --checking time parameter
1223 --if time parameter needed, check its presence
1224 if timeLimit~="No Limit" and timeLimit~="Chat" and time == nil
1225 then
1226 --this activity needs a time limit and no limit is given
1227 -- debugInfo(colorTag(255,0,0).."Time limit <" .. timeLimit .."> need a time limit parameter!")
1228 return nil
1231 --check season validity
1232 if (timeLimit == "Season") and (Logic.find(Logic.Seasons, time) == nil)
1233 then
1234 -- debugInfo(colorTag(255,0,0).."Unknown season: " .. time)
1235 return nil
1238 --check day validity
1239 if (timeLimit == "Day") and (Logic.find(Logic.Days, time) == nil)
1240 then
1241 debugInfo(colorTag(255,0,0).."Uknown week day: " .. time)
1242 return nil
1245 if (timeLimit == "Month") and (Logic.find(Logic.Months, time)== nil)
1246 then
1247 -- debugInfo(colorTag(255,0,0,0).."Uknown month: " .. time)
1248 return nil
1251 activityStep = r2.newComponent("ActivityStep")
1252 activityStep.Activity = activity
1253 activityStep.TimeLimit = timeLimit
1254 activityStep.ActivityZoneId = zoneId
1255 activityStep.TimeLimitValue = time
1256 else
1257 -- debugInfo(colorTag(255,0,0).."Unknown activity !")
1259 return activityStep
1262 Logic.createState = function()
1263 local aiState = r2.newComponent("RtAiState")
1264 aiState.Name = aiState.Id
1265 Logic.StatesByName = Logic.StatesByName .."\n" .. aiState.Name
1266 return aiState
1269 --create the AiStates necessay to translate this step
1270 Logic.createStepStates = function(step, context)
1271 local states = {}
1272 local state = Logic.createState()
1273 table.insert(states, state)
1274 table.insert(context.RtAct.AiStates, state)
1275 if step.Activity == "Patrol"
1276 then
1277 local state = Logic.createState()
1278 table.insert(states, state)
1279 table.insert(context.RtAct.AiStates, state)
1281 return states
1284 --assign a zone or a road to an AiState
1285 --if invert is true, invert the road
1286 Logic.assignZone = function(rtAiState, zone, invert)
1287 assert( zone and type(zone) == "userdata")
1288 local points = zone.Points
1289 assert( points ~= nil)
1291 local size = points.Size + 1
1292 rtAiState.Pts = {}
1293 local i =0
1294 local j
1296 local k, v = next(points, nil)
1297 while k ~= nil
1299 assert(v ~= nil)
1300 i = i +1
1301 if invert == true
1302 then
1303 j = size - i
1304 else
1305 j = i
1307 rtAiState.Pts[j]={}
1308 rtAiState.Pts[j].x = r2.getWorldPos(v).x
1309 rtAiState.Pts[j].y = r2.getWorldPos(v).y
1310 rtAiState.Pts[j].z = r2.getWorldPos(v).z
1311 k, v = next(points, k)
1315 --create all the states used in this activity Sequence
1316 Logic.createActivityStates = function(context, sequence)
1317 assert( sequence ~= nil)
1319 local activityStates ={}
1320 --activity's initial stat, aiStopStatee
1322 -- init state
1323 local aiStartState = r2.newComponent("RtAiState")
1324 aiStartState.Name = aiStartState.Id
1325 Logic.StatesByName = aiStartState.Name
1326 aiStartState.AiMovement = "idle" -- "stand_on_start_point"
1327 table.insert(context.RtAct.AiStates, aiStartState)
1330 -- end state
1331 local aiStopState = r2.newComponent("RtAiState")
1332 aiStopState.Name = aiStopState.Id
1333 --Logic.StatesByName = aiStopState.Name
1334 aiStopState.AiMovement = "idle" -- "stand_on_start_point"
1335 table.insert(context.RtAct.AiStates, aiStopState)
1337 activityStates[sequence.InstanceId]= { aiStartState, aiStopState}
1340 if (sequence.Components == nil) then assert(nil) end
1341 --creation of the states of the step
1342 local k, v = next(sequence.Components, nil)
1343 while k do
1344 local states = Logic.createStepStates(v, context)
1345 activityStates[v.InstanceId]= states
1346 k, v = next(sequence.Components, k)
1348 Logic.ActivitiesStates[sequence.InstanceId] = activityStates
1351 Logic.translateActivitySequence = function(context, hlComponent, activitySequence, sequenceId, rtNpcGrp)
1352 assert(rtNpcGrp ~= nil)
1353 if context.Real == false
1354 then
1355 return
1357 Logic.ActionStepCounter = 0
1358 Logic.ChatSequenceCounter = 0
1359 --Logic.States = {}
1360 Logic.CurrentActivity = activitySequence
1361 local ok = false
1363 local nbSteps = activitySequence.Components.Size
1364 local aiState
1365 local action
1366 local event
1367 local sequence = activitySequence
1370 if sequence.Components.Size ==0
1371 then
1372 return
1376 Logic.initSequence(context, rtNpcGrp)
1377 if Logic.ActivitiesStates[sequence.InstanceId] then
1378 Logic.States = Logic.ActivitiesStates[sequence.InstanceId]
1379 else
1380 Logic.States = ""
1385 local i =1
1386 local k, activityStep = next(sequence.Components, nil)
1387 while k do
1388 --translate step
1389 Logic.translateActivityStep(context, hlComponent, activitySequence, activityStep, i, rtNpcGrp)
1390 i = i + 1
1391 k, activityStep = next(sequence.Components, k)
1395 --create actions to repeat the sequence
1396 if sequence.Repeating == 1
1397 then
1399 local code =
1400 "//sequence will repeat"..
1401 "oldChatSequenceVar = " .. Logic.chatSequenceVar .. ";\n" ..
1402 "RoadCountLimit=0;\n" ..
1403 "oldActivityStepVar = " .. Logic.activityStepVar .. ";\n" ..
1404 "oldActivityStepVar2 = " .. Logic.activityStepVar .. " + 1" .. ";\n" ..
1405 "v2=0;\n" ..
1406 "()setTimer(1, " ..Logic.activityStepTimerId .. ");\n"
1407 -- .. "()setEvent(" .. Logic.EndOfActivitySequenceEvent ..");\n"
1409 local action = r2.Translator.createAction("code", code)
1410 action.Name = "repeat_sequence"
1411 table.insert(Logic.SequenceAction.Children, action)
1413 else
1415 local backupState =
1416 "//sequence will not repeat"..
1417 "oldChatSequenceVar = " .. Logic.chatSequenceVar .. ";\n" ..
1418 "RoadCountLimit=0;\n"..
1419 "oldActivityStepVar = " .. Logic.activityStepVar .. ";\n" ..
1420 "oldActivityStepVar2 = " .. Logic.activityStepVar .. " + 1" .. ";\n"
1422 local stateName = Logic.ActivitiesStates[sequence.InstanceId][sequence.InstanceId][2].Id
1424 local setNextActivityState = "()postNextState(\"" .. r2.getNamespace() .. stateName .."\");\n"
1426 local action = r2.Translator.createAction("code", backupState
1427 -- .."()setEvent(" .. Logic.EndOfActivitySequenceEvent ..");\n"
1428 ..setNextActivityState)
1431 action.Name = "end_of_activity_sequence"
1432 table.insert(Logic.SequenceAction.Children, action)
1435 Logic.SequenceEvent.StatesByName = Logic.StatesByName
1436 Logic.DialogEvent = nil
1437 Logic.SequenceEvent = nil
1442 Logic._obsolete_TranslateScriptAction = function(context, step, nextTime)
1443 local actionType = Logic.getAction(step)
1444 assert(actionType~= nil)
1445 -- debugInfo(colorTag(0,255,0).. actionType)
1447 if actionType == "stop_actions"
1448 then
1449 local action = r2.Translator.createAction("set_timer_" ..Logic.chatTimer, "0")
1450 return action
1453 if actionType == "start_mission"
1454 then
1455 local counterMission = context.Components[step.Parameter]
1456 local action = r2.Translator.createAction("trigger_event_1", context.RtCounters[counterMission.InstanceId].RtGroup.Name)
1457 -- debugInfo("action created!!")
1458 return action
1461 if 0==1 and actionType == "go_to_step"
1462 then
1463 --TODO
1464 local param = tonumber(step.Parameter)
1465 debugInfo("param = " .. param)
1466 if (param < 1) or (Logic.CurrentActivity.Components[param]== nil)
1467 then
1468 -- debugInfo(colorTag(255,0,0).."Impossible to go to step " .. param .." !")
1469 return nil
1471 debugInfo(context.Feature.Class)
1472 return Logic.selectActivityStep(param)
1475 if actionType == "set_activity"
1476 then
1477 local group = nil
1478 local param
1479 local rtGroup
1480 if step.Who ~= "" and step.Who ~= nil
1481 then
1482 group = step.Who
1483 rtGroup = r2.Translator.getRtGroup(context, group)
1486 param = tonumber(step.Parameter)
1488 -- debugInfo("param = " .. param)
1490 local action
1491 if group ~= nil
1492 then
1493 action = r2.Translator.createAction("begin_state", Logic.getActivityInitialStateName(group, param, context))
1494 assert(action ~= nil)
1495 local index = Logic.addTriggeredAction(context, context.RtGroups[group].Name, action)
1496 action = r2.Translator.createAction("modify_variable", rtGroup.Name ..":" ..Logic.triggerEventVar .." = " .. index)
1497 action.Name ="set_activity"
1498 else
1499 action = r2.Translator.createAction("begin_state", Logic.getActivityInitialStateName(context.Group.Name, param, context))
1500 assert(action ~= nil)
1502 return action
1505 local action = r2.Translator.createAction(actionType)
1506 assert(action ~= nil)
1507 return action
1513 Logic.translateChatAction = function(context, chatSequenceNumber, chatStepNumber, chatSequence, chatStep, chatAction, rtMAction)
1514 local getRtId = r2.Features["TextManager"].getRtId
1515 if chatAction.Class == "ChatAction"
1516 then
1517 local who = r2.Utils.getNpcParam( tostring( chatAction.Who), context)
1518 -- create say action
1519 if not who then
1521 local whoInstance = r2:getInstanceFromId( tostring(chatAction.Who) )
1522 local chatSequenceInstance = r2:getInstanceFromId(chatSequence.InstanceId)
1524 local whoName = ""
1525 if whoInstance then whoName = "(" .. whoInstance.Name ..")" end
1527 if false then
1528 printWarning( "Error in ChatStep '" .. chatStep:getName()
1529 .. "' of the ChatSequence '" .. chatSequence:getName() .. "'"
1530 .. " the field Who '" .. chatAction.Who .."' is invalid " )
1533 return nil
1537 if chatAction.Says ~= "" and chatAction.Says ~= nil
1538 then
1539 local param = getRtId(context, tostring(chatAction.Says))
1540 if param then
1541 action = r2.Translator.createAction("npc_say", param, who);
1543 -- action = r2.newComponent("RtNpcEventHandlerAction")
1544 -- action.Action = "npc_say"
1546 -- action.Parameters = who .."\n" .. param
1547 table.insert(rtMAction.Children, action)
1548 else
1549 debugInfo(colorTag(255,255,0).."WRN: Text " .. chatAction.Says .. " error")
1554 -- create emot action
1555 if tostring(chatAction.Emote) ~= "" and chatAction.Emote ~= nil
1556 then
1557 action = r2.newComponent("RtNpcEventHandlerAction")
1558 action.Action = "emot"
1559 action.Parameters = tostring(chatAction.Emote).."\n" .. who
1560 table.insert(rtMAction.Children, action)
1563 -- create facing action
1564 if tostring(chatAction.Facing) ~= "" and chatAction.Facing ~= nil
1565 then
1566 local facing = r2.Utils.getNpcParam(tostring(chatAction.Facing), context)
1567 if facing then
1568 action = r2.newComponent("RtNpcEventHandlerAction")
1569 action.Action = "facing"
1570 action.Parameters = facing .."\n" .. who
1571 table.insert(rtMAction.Children, action)
1572 else
1573 printWarning("Can not find npc")
1576 else
1577 printWarning( chatAction.Class .. " not implemented yet")
1581 Logic.translateChatStep = function(context, chatSequenceNumber, chatSequence, chatStepNumber, chatStep, rtActionSwitchChatStep)
1583 assert(chatStep)
1584 assert(chatStep.Class == "ChatStep")
1586 if chatStep.Actions.Size > 0 then
1588 local rtMAction = r2.Translator.createAction("multi_actions")
1589 table.insert(rtActionSwitchChatStep.Children, rtMAction)
1591 local k, chatAction = next(chatStep.Actions, nil)
1592 while k do
1593 Logic.translateChatAction(context, chatSequenceNumber, chatStepNumber, chatSequence, chatStep, chatAction, rtMAction)
1595 local oldChatAction = chatAction
1596 -- next wait
1599 if (chatStepNumber < chatSequence.Components.Size and chatSequence.Components[chatStepNumber ]) then
1601 local action = r2.Translator.createAction("code",
1602 "oldChatStepVar = " .. tostring(chatStepNumber)..";\n" ..
1603 Logic.chatStepVar .." = " .. tostring(chatStepNumber+1)..";\n" ..
1604 "()setTimer(" .. tostring(1+chatSequence.Components[chatStepNumber].Time*10) .. ", " .. Logic.chatTimerId .. ");\n");
1605 action.Name = "next"
1606 table.insert(rtMAction.Children, action)
1608 else
1609 local action = r2.Translator.createAction("code",
1610 "oldChatStepVar = " .. tostring(chatStepNumber)..";\n" ..
1611 Logic.chatStepVar .." = " .. tostring(chatStepNumber+1)..";\n" ..
1612 "()setEvent(" ..Logic.EndOfChatSequenceEvent ..");\n" ..
1613 "if (repeatSequence == 1)\n{\n " .. Logic.chatSequenceVar .."=" ..Logic.chatSequenceVar ..";\n" ..
1614 "}\n")
1616 action.Name = "end_of_chat_sequence"
1617 table.insert(rtMAction.Children, action)
1626 k, chatAction = next(chatStep.Actions, k)
1631 else
1632 local action = r2.Translator.createAction("null_action")
1633 action.Name = "empty_chat_step_" .. chatStepNumber
1634 table.insert(rtActionSwitchChatStep.Children, action)
1639 Logic.translateChatSequence = function (context, chatSequenceNumber, chatSequence, rtSwitchChatSequence)
1640 assert(chatSequence)
1641 assert(chatSequence.Class == "ChatSequence")
1642 if chatSequence.Components.Size > 0 then
1644 local rtActionSwitchChatStep = r2.Translator.createAction("switch_actions", Logic.chatStepVar)
1645 rtActionSwitchChatStep.Name = "switch_chat_step"
1646 table.insert(rtSwitchChatSequence.Children, rtActionSwitchChatStep)
1648 local chatStepNumber = 0
1650 -- initial wait
1652 local action = r2.Translator.createAction("code", "oldChatStepVar = 0;\n"
1653 .. Logic.chatStepVar .." = 1;\n()setTimer(" .. tostring( tonumber(chatSequence.Components[0].Time)*10 + 1) .. ", " .. Logic.chatTimerId ..");\n");
1654 action.Name = "initial_wait"
1655 table.insert(rtActionSwitchChatStep.Children, action)
1659 local k, chatStep = next(chatSequence.Components, nil)
1660 while k do
1661 chatStepNumber = chatStepNumber + 1
1662 Logic.translateChatStep(context, chatSequenceNumber, chatSequence, chatStepNumber, chatStep, rtActionSwitchChatStep)
1663 k, chatStep = next(chatSequence.Components, k)
1665 else
1666 local action = r2.Translator.createAction("null_action")
1667 action.Name = "empty_chat_sequence_" .. chatSequenceNumber
1668 table.insert(rtSwitchChatSequence.Children, action)
1672 Logic.translateChatSequences = function (context, hlComponent, behavior, rtNpcGrp)
1673 assert(behavior.ChatSequences)
1674 if behavior.ChatSequences.Size > 0 then
1675 assert(rtNpcGrp)
1678 local event = r2.Translator.createEvent("variable_" ..Logic.chatSequenceVar .."_changed", "", rtNpcGrp.Name)
1679 event.Name = "activity_sequence_changed"
1680 table.insert(context.RtAct.Events, event)
1682 local rtInitChatStep = r2.Translator.createAction("code", "oldChatStepVar = -1;\n" .. Logic.chatStepVar .." = 0;\n()setTimer(1, " ..Logic.chatTimerId .. ");\n")
1683 rtInitChatStep.Name = "init_chat_step"
1684 table.insert(context.RtAct.Actions, rtInitChatStep)
1685 table.insert(event.ActionsId, rtInitChatStep.Id)
1689 local event = r2.Translator.createEvent("timer_" ..Logic.chatTimer .."_triggered", "", rtNpcGrp.Name)
1690 event.Name = "dialog_event"
1691 table.insert(context.RtAct.Events, event)
1693 local rtSwitchChatSequence = r2.Translator.createAction("switch_actions", Logic.chatSequenceVar)
1694 rtSwitchChatSequence.Name = "switch_chat_sequence"
1695 table.insert(context.RtAct.Actions, rtSwitchChatSequence)
1696 table.insert(event.ActionsId, rtSwitchChatSequence.Id)
1698 local chatSequenceNumber = 0
1699 local k, chatSequence = next(behavior.ChatSequences, nil)
1700 while k do
1701 context.Feature = nil
1702 chatSequenceNumber = chatSequenceNumber + 1
1703 Logic.translateChatSequence(context, chatSequenceNumber, chatSequence, rtSwitchChatSequence)
1704 k, chatSequence = next(behavior.ChatSequences, k)
1711 function Logic.isWanderActivity(activity)
1712 return activity == "Wander" or activity == "Go To Zone" or activity == "Rest In Zone" or activity == "Feed In Zone"
1713 or activity == "Hunt In Zone" or activity == "Guard Zone"
1717 -------------------------------------------------
1718 --create a transition to go to step number stepNb
1719 --set a timer to go to next step
1720 --select the step
1721 --goto the step's state
1722 Logic.createTransition = function(context, hlComponent, activitySequence, activityStep, activityStepIndex, stepAction)
1723 local findChatSequenceIdByInstanceId = function (chat)
1725 local parent = chat.ParentInstance.ChatSequences
1726 assert(parent)
1729 local nbSequence = 0
1730 local k, sequence = next(parent, nil)
1731 while k do
1732 if tostring(sequence.InstanceId) == tostring(chat.InstanceId) then return nbSequence end
1733 nbSequence = nbSequence + 1
1734 k, sequence = next(parent, k)
1736 return -1
1739 assert(activityStep)
1741 local chat = nil
1744 if activityStep.Chat ~= "" then
1745 chat = r2:getInstanceFromId( tostring(activityStep.Chat) )
1748 local code = ""
1751 local backupState = ""
1752 local setChatSequence = ""
1753 local setNextActivity = ""
1754 local setNextActivityTimer = ""
1755 local setNextActivityState = ""
1758 backupState =
1759 "oldChatSequenceVar = " .. Logic.chatSequenceVar .. ";\n" ..
1760 "RoadCountLimit=0;\n"..
1761 "oldActivityStepVar = " .. Logic.activityStepVar .. ";\n" ..
1762 "oldActivityStepVar2 = " .. Logic.activityStepVar.. " + 1;\n"
1765 if chat~= nil then
1766 local id = findChatSequenceIdByInstanceId( chat )
1767 assert(id ~= -1 )
1768 setChatSequence = Logic.chatSequenceVar .. " = " .. tostring( id ) .. ";\n"
1769 if (activityStep.Type == "Repeating") then
1770 setChatSequence = setChatSequence .. "repeatSequence = 1;\n"
1771 else
1772 setChatSequence = setChatSequence .. "repeatSequence = 0;\n"
1776 -- next activity
1777 setNextActivity = Logic.activityStepVar .. " = " .. activityStepIndex ..";\n"
1779 -- next activity timer
1780 local param = Logic.getTimeLimit(activityStep)
1781 if param ~= nil then
1782 if Logic.isWanderActivity(activityStep.Activity) then
1783 -- The time limite is use by the activity
1784 else
1785 setNextActivityTimer = "()setTimer(" .. param ..", " ..Logic.activityStepTimerId .. ");\n"
1789 local states = Logic.States[activityStep.InstanceId]
1790 local stateName = states[1].Name
1792 -- next activity state
1794 setNextActivityState = "()postNextState(\"" .. r2.getNamespace() .. stateName .."\");\n"
1795 local action = r2.Translator.createAction("code", backupState .. setChatSequence .. setNextActivity .. setNextActivityTimer .. setNextActivityState)
1798 action.Name = "process_activity_step" .. activityStepIndex
1800 if stepAction then
1801 local tmpAction = r2.Translator.createAction("multi_actions")
1802 table.insert(tmpAction.Children, action)
1803 table.insert(tmpAction.Children, stepAction)
1804 action = tmpAction
1807 action.Name = "process_activity_step" .. activityStepIndex
1808 return action
1813 ------------------------------------------
1814 --crée une action qui permet de
1815 --sélectionner une séquence de chat
1816 Logic.selectDialog = function(dialogNb, rtNpcGrp)
1817 local action
1818 local prefix = ""
1819 if (rtNpcGrp ~= nil) then
1820 prefix = r2.getNamespace() .. rtNpcGrp .. "."
1823 action = r2.Translator.createAction("code",
1824 prefix .."oldChatSequenceVar =" .. prefix..Logic.chatSequenceVar ..";\n" ..
1825 prefix .. Logic.chatSequenceVar .." = " ..(dialogNb-1)..";\n")
1826 action.Name = "select_dialog"
1827 return action
1830 --create the actions and events necessary to choose
1831 --the dialog while running sequence
1832 Logic.initDialog = function(context)
1833 local event = r2.Translator.createEvent("variable_" ..Logic.chatSequenceVar .."_changed", "all_sequence_states", context.Group.Name)
1834 event.Name = "change_dialog_event"
1835 Logic.DialogEvent2 = event
1836 local action
1837 local mAction = r2.Translator.createAction("multi_actions")
1838 action = r2.Translator.createAction("code", "oldChatStepVar = " .. Logic.chatStepVar ..";\n" .. Logic.chatStepVar .." = 0;\n")
1839 action.Name = "reset_dialog"
1840 table.insert(mAction.Children, action)
1841 action = r2.Translator.createAction("switch_actions", Logic.chatSequenceVar)
1842 action.Name = "init_dialog_timer"
1843 table.insert(mAction.Children, action)
1844 Logic.DialogAction2 = action
1845 table.insert(context.RtAct.Events, event)
1846 table.insert(context.RtAct.Actions, mAction)
1847 table.insert(event.ActionsId, mAction.Id)
1850 event = r2.Translator.createEvent("timer_" ..Logic.chatTimer .."_triggered", "all_sequence_states", context.Group.Name)
1851 event.Name = "dialog_event"
1852 Logic.DialogEvent = event
1853 table.insert(context.RtAct.Events, event)
1855 Logic.DialogAction = r2.Translator.createAction("switch_actions", Logic.chatSequenceVar)
1856 table.insert(context.RtAct.Actions, Logic.DialogAction)
1857 table.insert(event.ActionsId, Logic.DialogAction.Id)
1860 Logic.initSequence = function(context, rtNpcGrp)
1861 assert(context)
1862 assert(rtNpcGrp)
1864 event = r2.Translator.createEvent("timer_" ..Logic.activityStepTimer .."_triggered", "all_sequence_states", rtNpcGrp.Name)
1865 event.Name = "sequence_event"
1866 Logic.SequenceEvent = event
1867 table.insert(context.RtAct.Events, event)
1869 Logic.SequenceAction = r2.Translator.createAction("switch_actions", Logic.activityStepVar)
1870 table.insert(context.RtAct.Actions, Logic.SequenceAction)
1871 table.insert(event.ActionsId, Logic.SequenceAction.Id)
1874 -- ust to implement translateEvents used to implement event created for implementing
1875 Logic.translateEvent = function( context, hlComponent, activitySequence, activityStep, activityStepIndex, event, rtNpcGrp, statesByName)
1876 local chat = nil
1877 -- context, groups, states, actionToAdd)
1878 local eventType, eventParam = Logic.getEvent(event)
1879 local eventHandler = nil
1881 if context.Events[event.InstanceId] == nil
1882 then
1883 eventHandler = r2.Translator.createEvent(eventType, states, groups)
1884 assert(eventHandler ~= nil)
1886 local stepAction = Logic.translateChatStep(context, event.Action, nil)
1888 if actionToAdd ~= nil
1889 then
1890 table.insert(stepAction.Children, actionToAdd)
1893 assert(stepAction ~= nil)
1895 table.insert(context.RtAct.Actions, stepAction)
1896 table.insert(eventHandler.ActionsId, stepAction.Id)
1897 context.Events[event.InstanceId] = eventHandler
1898 else
1899 eventHandler = context.Events[event.InstanceId]
1901 if string.find(eventHandler.StatesByName, states) == nil
1902 then
1903 eventHandler.StatesByName = eventHandler.StatesByName .. "\n" .. states
1906 if string.find(eventHandler.GroupsByName, groups) == nil
1907 then
1908 eventHandler.GroupsByName = eventHandler.GroupsByName .. "\n" .. groups
1913 return eventHandler
1916 -- translateEvents
1917 Logic.translateEvents = function(context, hlComponent, activitySequence, activityStep, activityStepIndex, rtNpcGrp, statesByName)
1919 local activityStep
1921 local last = nil
1923 if activityStepIndex == activitySequence.Components.Size then
1924 last = true
1928 local k, eventId = next(step.EventsIds, nil)
1930 local eventHandler = r2:getInstanceFromId(eventId)
1931 assert(eventHandler ~= nil)
1932 local action = nil
1934 if eventHandler.Condition.Type == "At Destination" then
1935 if step.Activity == "Follow Route" and last ~= true then
1936 action = Logic.selectActivityStep(activityStepIndex + 1)
1940 --the event returned here is a RtNpcEventHandler
1941 event = translateEvent(context, groups, states, action)
1942 assert(event ~= nil)
1944 table.insert(context.RtAct.Events, event)
1945 k, eventId = next(step.EventsIds, k)
1949 --translate an activity step
1950 Logic.translateActivityStep = function(context, hlComponent, activitySequence, activityStep, activityStepIndex, rtNpcGrp)
1952 --translate this activity activityStep's events
1953 assert(rtNpcGrp)
1954 local aiState
1955 local aiState2
1956 local statesByName
1957 local groupsByName = rtNpcGrp.Name
1958 local zone = nil
1959 local chat = nil
1960 local aiScriptDebug = false
1962 local activityStep = activityStep
1964 if activityStep.Chat ~= "" then
1965 chat = r2:getInstanceFromId(activityStep.Chat)
1966 if not chat then
1967 printErr("translation error: in the activitySequence " .. activitySequence.Name .. " in component " .. hlComponent.Name .. ": " .. " the chat sequence associated to this activity sequence can not be found")
1968 return nil
1972 local states = Logic.States[activityStep.InstanceId]
1973 --states creation
1974 aiState = states[1] -- 1 is first ( a lua object not a instance )
1976 --setting state AiMovement
1977 aiState.AiMovement = Logic.getAiMovement(activityStep.Activity)
1978 assert(aiState.AiMovement ~= "")
1979 --setting state zone or road
1982 local positionalActivity= {["Patrol"] = "road",
1983 ["Wander"] = "zone",
1984 ["Repeat Road"] = "road",
1985 ["Follow Route"] = "road",
1986 ["Rest In Zone"] = "zone",
1987 ["Feed In Zone"] = "zone",
1988 ["Hunt In Zone"] = "zone",
1989 ["Guard Zone"] = "zone",
1990 ["Go To Zone"] = "zone",
1992 if positionalActivity[activityStep.Activity] then
1993 local zone = r2:getInstanceFromId(activityStep.ActivityZoneId)
1994 if zone == nil then
1995 aiState = states[1]
1996 aiState.AiMovement = "idle"
1997 return aiState
1998 else
1999 if positionalActivity[activityStep.Activity] == "zone" then
2000 if table.getn(zone.Points) < 3 then
2001 aiState = states[1]
2002 aiState.AiMovement = "idle"
2003 return aiState
2005 else
2006 if table.getn(zone.Points) < 2 then
2007 aiState = states[1]
2008 aiState.AiMovement = "idle"
2009 return aiState
2011 end
2018 if activityStep.Activity == "Patrol" then
2019 local zone = r2:getInstanceFromId(activityStep.ActivityZoneId)
2020 if (zone == nil)
2021 then
2022 printErr("translation error: in the activitySequence " .. activitySequence.Name .. " in component " .. hlComponent.Name .. ": " .. " the zone associated to the action can not be found")
2023 return nil
2026 --un etat aller, un etat retour
2027 aiState2 = states[2]
2028 aiState2.AiMovement = "follow_route"
2029 Logic.assignZone(aiState, zone, false)
2030 Logic.assignZone(aiState2, zone, true)
2032 statesByName = aiState.Name .."\n" .. aiState2.Name
2033 elseif activityStep.Activity == "Repeat Road" or activityStep.Activity == "Follow Route" or activityStep.Activity == "Wander"
2034 or activityStep.Activity == "Rest In Zone" or activityStep.Activity == "Feed In Zone" or activityStep.Activity == "Hunt In Zone"
2035 or activityStep.Activity == "Guard Zone" or activityStep.Activity == "Go To Zone" then
2036 local zone = r2:getInstanceFromId(activityStep.ActivityZoneId)
2037 if (zone == nil) then
2038 printErr("translation error: in the activitySequence " .. activitySequence.Name .. " in component " .. hlComponent.Name .. ": " .. " the zone associated to the action can not be found")
2039 return nil
2041 Logic.assignZone(aiState, zone, false)
2042 statesByName = aiState.Name
2043 else
2044 statesByName = aiState.Name
2048 if activityStep.Activity == "Repeat Road" then
2049 local action
2050 local event
2051 --when at end of the road, ...
2052 event = r2.Translator.createEvent("destination_reached_all", statesByName, groupsByName)
2053 table.insert(context.RtAct.Events, event)
2054 --return to the start of the road
2055 local repeatCount = activityStep.RoadCountLimit
2056 if not repeatCount then repeatCount = 2 end
2058 action = r2.Translator.createAction("next_road", groupsByName, aiState.Name, activityStepIndex , repeatCount)
2059 table.insert(context.RtAct.Actions, action)
2060 table.insert(event.ActionsId, action.Id)
2062 elseif activityStep.Activity == "Patrol" then
2063 local action
2064 local event
2065 local repeatCount = activityStep.RoadCountLimit
2066 if not repeatCount then repeatCount = 2 end
2067 event = r2.Translator.createEvent("destination_reached_all", aiState.Name, groupsByName)
2068 table.insert(context.RtAct.Events, event)
2069 action = r2.Translator.createAction("next_road", groupsByName, aiState2.Name, activityStepIndex, repeatCount)
2070 action.Name = "return"
2071 table.insert(context.RtAct.Actions, action)
2072 table.insert(event.ActionsId, action.Id)
2074 event = r2.Translator.createEvent("destination_reached_all", aiState2.Name, groupsByName)
2075 table.insert(context.RtAct.Events, event)
2076 action = r2.Translator.createAction("next_road", groupsByName, aiState.Name, activityStepIndex , repeatCount)
2077 action.Name = "go"
2078 table.insert(context.RtAct.Actions, action)
2079 table.insert(event.ActionsId, action.Id)
2081 elseif activityStep.Activity == "Follow Route" or activityStep.Activity == "Go To Start Point" or activityStep.Activity == "Go To Zone" then
2082 local action
2083 local event
2084 event = r2.Translator.createEvent("destination_reached_all", aiState.Name, groupsByName)
2085 table.insert(context.RtAct.Events, event)
2086 action = Logic.selectActivityStep(activityStepIndex + 1)
2087 table.insert(context.RtAct.Actions, action)
2088 table.insert(event.ActionsId, action.Id)
2089 elseif activityStep.Activity == "Rest In Zone" then
2090 local wanderTime = 100
2091 local restTime = 300
2092 r2.Translator.createActivityInZone(context, aiState.Name, groupsByName, "Rest", Logic.activityInternalTimerId, wanderTime, restTime, aiScriptDebug)
2093 elseif activityStep.Activity == "Feed In Zone" then
2094 local wanderTime = 50
2095 local feedTime = 150
2096 r2.Translator.createActivityInZone(context, aiState.Name, groupsByName, "Eat", Logic.activityInternalTimerId, wanderTime, feedTime, aiScriptDebug)
2097 elseif activityStep.Activity == "Hunt In Zone" then
2098 local wanderTime = 100
2099 local alertTime = 25
2100 local eatTime = 80
2101 r2.Translator.createHuntActivityInZone(context, aiState.Name, groupsByName, Logic.activityInternalTimerId, wanderTime, alertTime, eatTime, aiScriptDebug)
2102 elseif activityStep.Activity == "Guard Zone" then
2103 r2.Translator.createSimpleActivityInZone(context, aiState.Name, groupsByName, "Alert", false, aiScriptDebug)
2107 if Logic.isWanderActivity(activityStep.Activity) and activityStep.TimeLimit == "Few Sec" then
2108 local event = r2.Translator.createEvent("destination_reached_all", aiState.Name, groupsByName)
2109 table.insert(context.RtAct.Events, event)
2110 local number = tonumber(activityStep.TimeLimitValue)
2111 if number == nil then
2112 number = 0
2114 local action = r2.Translator.createAction("wander_destination_reached", groupsByName, aiState.Name, activityStepIndex, number)
2115 table.insert(context.RtAct.Actions, action)
2116 table.insert(event.ActionsId, action.Id)
2119 local stepAction = nil
2120 if activityStep.Activity == "Stand Up" then
2121 stepAction = r2.Translator.createAction("stand_up", rtNpcGrp.Id )
2122 elseif activityStep.Activity == "Sit Down" then
2123 stepAction = r2.Translator.createAction("sit_down", rtNpcGrp.Id )
2127 -- translate event create by activitySequence (eg patrol)
2128 if activityStep.EventsIds.Size ~= 0
2129 then
2130 Logic.translateEvents(context, hlComponent, activitySequence, activityStep, activityStepIndex, rtNpcGrp, statesByName)
2135 --go to next activityStep
2136 local action = Logic.createTransition(context, hlComponent, activitySequence, activityStep, activityStepIndex, stepAction)
2137 table.insert(Logic.SequenceAction.Children, action)
2140 -- if ActivityStep.TimeLimit == "Chat" creates a eventhandler to go to next state
2142 if activityStep.TimeLimit == "Chat" then
2143 local action
2144 local condition
2145 local event
2147 local number = Logic.findChatSequenceIdByInstanceId(hlComponent, chat.InstanceId)
2148 if (number == nil or number == -1) then
2149 printWarning("Error in translation: in component '" .. hlComponent.Name .. " the chat sequence selected as time limit of Activity Step " .. activityStepIndex .. " does not exist.")
2155 event = r2.Translator.createEvent("user_event_8", aiState.Name, rtNpcGrp.Id)
2156 table.insert(context.RtAct.Events, event)
2160 condition = r2.Translator.createAction("condition_if", "v0 == "..tostring(number-1))
2161 table.insert(context.RtAct.Actions, condition)
2164 action = Logic.selectActivityStep(activityStepIndex + 1)
2165 table.insert(condition.Children, action)
2166 table.insert(event.ActionsId, condition.Id)
2171 assert(State ~= "")
2172 return aiState
2175 ---------------------------------------------------------------------------------------
2176 --helpers functions--
2177 ---------------------------------------------------------------------------------------
2180 Logic.getAiMovement = function(activity)
2181 assert(activity and type(activity) == "string")
2182 if (activity == "Follow Route") or (activity == "Patrol") or (activity == "Repeat Road") then
2183 return "follow_route"
2184 elseif activity == "Deploy" then
2185 return "stand_on_vertices"
2186 elseif activity == "Wander" or activity == "Go To Zone" or activity == "Rest In Zone" or activity == "Feed In Zone"
2187 or activity == "Hunt In Zone" or activity == "Guard Zone" then
2188 return "wander"
2189 elseif activity == "Stand Still" or activity == "Inactive" or activity == "Stand Up" or activity == "Sit Down" then
2190 return "idle"
2191 elseif activity == "Stand On Start Point" or activity == "Go To Start Point" then
2192 return "stand_on_start_point"
2195 printWarning("Undef activity '"..activity.."'")
2196 assert(nil)
2197 return ""
2200 Logic.getAction = function(action)
2201 local action_type = action.Action
2203 if action_type == "Sit Down"
2204 then
2205 return "sit_down"
2207 if action_type == "Stand Up"
2208 then
2209 return "stand_up"
2211 if action_type == "Go To Step"
2212 then
2213 if action.Parameter == nil or action.Parameter == ""
2214 then
2215 return nil
2217 return "go_to_step"
2219 if action_type == "Set Activity"
2220 then
2221 if action.Parameter == nil or action.Parameter == ""
2222 then
2223 return nil
2225 return "set_activity"
2228 if action_type == "Stop Actions"
2229 then
2230 return "stop_actions"
2233 if action_type == "Start Mission"
2234 then
2235 return "start_mission"
2238 return nil
2241 Logic.getEvent = function(Event)
2242 local i = Logic.find(Logic.EventTypes, Event.Condition.SourceType)
2243 --Time event type
2244 if i == 0
2245 then
2248 --place event type
2249 if i == 1
2250 then
2253 --entity event type
2254 if i == 2
2255 then
2256 if Event.Condition.Type == "At Destination"
2257 then
2258 return "destination_reached_all"
2261 if Event.Condition.Type == "Is Attacked"
2262 then
2263 return "group_under_attack"
2266 if Event.Condition.Type == "Enters State"
2267 then
2268 return "start_of_state"
2271 if Event.Condition.Type == "Leaves State"
2272 then
2273 return "end_of_state"
2275 if Event.Condition.Type == "Activity Is"
2276 then
2280 --State Machine event type
2281 if i == 3
2282 then
2285 --Counter event type
2286 if i == 4
2287 then
2288 local counterName = Event.Parameter
2289 local param
2291 if counterName == nil
2292 then
2296 if string.find(Event.Condition.Type, "v%d_changed") ~= nil
2297 then
2298 return "variable_" ..Event.Condition.Type
2301 if Event.Condition.Type == "Equals"
2302 then
2303 param = " = "
2304 else
2305 if Event.Condition.Type == "Lesser"
2306 then
2307 param = " < "
2308 else
2309 if Event.Condition.Type == "Greater"
2310 then
2311 param = " > "
2312 else
2313 param = nil
2317 if param == nil
2318 then
2319 return nil
2321 param = param ..Event.Condition.ConditionParameter
2323 return "variable_changed", param
2327 Logic.checkEvent = function(eventMode, sourceType, sourceId, conditionType, parameter)
2328 local eventTypeInd = Logic.find(Logic.EventTypes, sourceType)
2329 local conditionTypeInd
2330 if eventTypeInd == nil
2331 then
2332 return false
2335 --{"Time", "Place", "Entity or Group", "State Machine", "Counter"}
2337 conditionTypeInd = Logic.find(Logic.ConditionTypes[eventTypeInd], conditionType)
2338 if eventTypeInd == nil
2339 then
2340 return false
2343 --Time event type
2344 if eventTypeInd == 0
2345 then
2348 --Place event type
2349 if eventTypeInd == 1
2350 then
2353 --Entity or Group event type
2354 if eventTypeInd == 2
2355 then
2356 if parameter == nil or parameter == ""
2357 then
2358 if conditionType == "At Destination" or conditionType == "Is Attacked"
2359 then
2360 return true
2361 else
2362 return false
2364 else
2365 if conditionType == "Enters State" or conditionType == "Leaves State"
2366 then
2367 return true
2368 else
2369 return false
2374 --State Machine event type
2375 if eventTypeInd == 3
2376 then
2379 --Counter event type
2380 if eventTypeInd == 4
2381 then
2382 if string.find(conditionType, "v%d_changed") ~= nil
2383 then
2384 return true
2386 if conditionType == "Lesser" or conditionType == "Greater" or conditionType == "Equals"
2387 then
2388 return true
2392 return false
2396 Logic.fillCondition = function(condition, sourceType, sourceId, conditionType, conditionParameter)
2397 condition.SourceType = sourceType
2398 condition.SourceId = sourceId
2399 condition.Type = conditionType
2400 condition.ConditionParameter = conditionParameter
2403 Logic.fillEvent = function(event, eventMode, sourceType, sourceId, conditionType, conditionParameter)
2404 if Logic.checkEvent(eventMode, sourceType, sourceId, conditionType, conditionParameter) == false
2405 then
2406 assert(0)
2407 return false
2410 Logic.fillCondition(event.Condition, sourceType, sourceId, conditionType, conditionParameter)
2411 event.EventMode = eventMode
2412 return true
2414 -----------------------------------------
2415 --genere le parametre de l'action set_timer
2416 Logic.getTimeLimit = function(step)
2417 local param = ""
2419 if step.TimeLimit == "Few Sec" then
2420 local limit = tonumber(step.TimeLimitValue)
2421 if limit == nil then
2422 limit = 0
2424 limit = 1 + limit * 10
2425 param = tostring( limit )
2426 return param
2428 return nil
2431 Logic.getActivityInitialStateName = function(groupId, activityNb, context)
2432 local group = context.Components[groupId]
2433 local activity = group.Components[1].Behavior.Activities[activityNb]
2435 if activity == nil
2436 then
2437 return nil
2440 local activityStates = Logic.ActivitiesStates[activity.InstanceId]
2441 return activityStates[activity.InstanceId][0].Name
2444 --return the states used to represent this step activity
2445 Logic.getActivityStepStates = function(activity, stepNb)
2446 local activityStates = Logic.ActivitiesStates[activity.InstanceId]
2447 local states = activityStates[activity.Components[stepNb].InstanceId]
2448 return states
2451 Logic.find = function(array, elem)
2452 local i = 0
2453 for k, v in pairs(array)
2455 if k ~="Keys"
2456 then
2457 if elem == v
2458 then
2459 return i
2461 i = i + 1
2464 return nil
2469 Logic.findChatSequenceIdByInstanceIdImpl = function(instance, instanceId)
2470 local behvior = instance:getBehavior()
2471 local k, sequence = next(behvior.ChatSequences, nil)
2472 local nbSequence = 0
2473 while k do
2474 nbSequence = nbSequence + 1
2475 if tostring(sequence.InstanceId) == instanceId then return nbSequence end
2476 k, sequence = next(behvior.ChatSequences, k)
2478 return -1
2481 Logic.findChatSequenceIdByInstanceId = function(target, instanceId)
2482 local instance =target
2483 return Logic.findChatSequenceIdByInstanceIdImpl(instance, instanceId)
2487 -- target -> hlNpc or hlNpcGrp
2488 Logic.findChatStepIdByInstanceId = function(target, instanceId)
2489 assert( type(target) == "userdata")
2490 local nbSequence = 0
2491 local nbStep = 0
2493 local instance = target
2494 assert(instance ~= nil)
2495 local behavior = instance:getBehavior()
2496 assert(behavior ~= nil)
2497 local k2, sequence = next(behavior.ChatSequences, nil)
2498 while k2 do
2500 nbSequence = nbSequence + 1
2501 nbStep = 0
2502 local k, step = next(sequence.Components, nil)
2503 while k do
2504 nbStep = nbStep +1
2505 if tostring(step.InstanceId) == instanceId then return {nbStep, nbSequence} end
2506 k, step = next(sequence.Components, k)
2508 k2, sequence = next(behavior.ChatSequences, k2)
2510 assert(0)
2511 return {-1, -1}
2514 -- target is a NpcGrp or a Npc or a CustomNpc
2515 Logic.findActivitySequenceIdByInstanceId = function(target, instanceId)
2516 assert( type(target) == "userdata")
2518 local nbSequence = 0
2519 local behavior = nil
2521 behavior = target:getBehavior()
2523 if behavior == nil then
2524 debugInfo("Error: try to find activity Sequence on an unknown entity of type " .. target.Class )
2525 assert(nil)
2528 local npc = behavior.ParentInstance
2529 local grp = behavior.ParentInstance.ParentInstance
2530 if not npc:isGrouped() then grp = nil end
2533 local k, sequence = next(behavior.Activities, nil)
2534 while (k ~= nil) do
2536 nbSequence = nbSequence + 1
2537 if sequence.InstanceId == instanceId then
2538 if grp then return {nbSequence, grp} end
2539 if npc then return {nbSequence, npc} end
2540 assert(nil)
2542 k, sequence = next(behavior.Activities, k)
2544 return {-1, nil}
2547 Logic.findActivityStepIdByInstanceId = function(target, instanceId)
2548 assert( type(target) == "userdata")
2549 local nbSequence = 0
2550 local nbStep = 0
2551 local comp = target
2552 local behavior = comp:getBehavior()
2554 local k, sequence = next(behavior.Activities, nil)
2555 while k do
2557 if tostring(sequence.InstanceId) == instanceId then
2558 assert(nil) -- use findActivityStep instead of findactivitySequence
2561 nbSequence = nbSequence + 1
2562 nbStep = 0
2563 local k2, step = next(sequence.Components, nil)
2564 while (k2) do
2565 nbStep = nbStep +1
2566 if tostring(step.InstanceId) == instanceId then return {nbStep, nbSequence} end
2567 k2, step = next(sequence.Components, k2)
2569 k, sequence = next(behavior.Activities, k)
2571 return {-1, -1}
2578 Logic.selectActivityStep = function(stepNb)
2579 local action
2580 stepNb = stepNb - 1
2582 action = r2.Translator.createAction("code",
2583 Logic.activityStepVar .. " = " .. stepNb ..";\n"
2584 .. "()setTimer(1, " ..Logic.activityStepTimerId .. ");\n")
2585 action.Name = "select_activity_step " .. stepNb
2587 return action
2592 ----------------------------------------------------------------------------
2593 -- add a line to the event menu
2595 local component = Logic.Components.ChatSequence
2598 ----------------------------------------------------------------------------
2599 -- add a line to the event menu
2600 function component:getLogicTranslations()
2602 local logicTranslations = {
2603 ["ApplicableActions"] = {
2604 ["starts dialog"] = { menu=i18n.get( "uiR2AA0ChatSeqStart" ):toUtf8(),
2605 text=i18n.get( "uiR2AA1ChatSeqStart" ):toUtf8()},
2606 ["stops dialog"] = { menu=i18n.get( "uiR2AA0ChatSeqStop" ):toUtf8(),
2607 text=i18n.get( "uiR2AA1ChatSeqStop" ):toUtf8()},
2608 ["starts chat"] = { menu=i18n.get( "uiR2AA0ChatStepStart" ):toUtf8(),
2609 text=i18n.get( "uiR2AA1ChatStepStart" ):toUtf8()},
2610 ["continues dialog"] = { menu=i18n.get( "uiR2AA0ChatStepContinue" ):toUtf8(),
2611 text=i18n.get( "uiR2AA1ChatStepContinue" ):toUtf8()},
2613 ["Events"] = {
2614 ["start of dialog"] = { menu=i18n.get( "uiR2Event0ChatSeqStart" ):toUtf8(),
2615 text=i18n.get( "uiR2Event1ChatSeqStart" ):toUtf8()},
2616 ["end of dialog"] = { menu=i18n.get( "uiR2Event0ChatSeqEnd" ):toUtf8(),
2617 text=i18n.get( "uiR2Event1ChatSeqEnd" ):toUtf8()},
2618 ["start of chat"] = { menu=i18n.get( "uiR2Event0ChatStepStart" ):toUtf8(),
2619 text=i18n.get( "uiR2Event1ChatStepStart" ):toUtf8()},
2620 ["end of chat"] = { menu=i18n.get( "uiR2Event0ChatStepEnd" ):toUtf8(),
2621 text=i18n.get( "uiR2Event1ChatStepEnd" ):toUtf8()},
2623 ["Conditions"] = {
2624 ["is in dialog"] = { menu=i18n.get( "uiR2Test0ChatSeq" ):toUtf8(),
2625 text=i18n.get( "uiR2Test1ChatSeq" ):toUtf8()},
2626 ["is not in dialog"] = { menu=i18n.get( "uiR2Test0ChatNotSeq" ):toUtf8(),
2627 text=i18n.get( "uiR2Test1ChatNotSeq" ):toUtf8()},
2628 ["is in chat"] = { menu=i18n.get( "uiR2Test0ChatStep" ):toUtf8(),
2629 text=i18n.get( "uiR2Test1ChatStep" ):toUtf8()},
2632 return logicTranslations
2636 r2.Features["ActivitySequence"] = Logic