Merge branch 'fixes' into main/gingo-test
[ryzomcore.git] / ryzom / common / data_common / r2 / r2_logic_entities.lua
blob26b39193a7f83a690fe558ddb17c6a492d180279
1 local logicEntity =
3 BaseClass = "WorldObject",
4 Name="LogicEntity",
5 InEventUI = false,
7 Parameters = {},
8 ApplicableActions = {},
9 Events = {},
10 Conditions = {},
11 TextContexts = {},
12 TextParameters = {},
13 LiveParameters = {},
15 DisplayerProperties = "R2::CDisplayerLua",
16 DisplayerPropertiesParams = "logicEntityPropertySheetDisplayer",
17 PermanentTreeIcon = "r2ed_icon_permanent_macro_components.tga",
18 TreeIcon = "r2ed_icon_macro_components.tga",
19 SelectBarType = i18n.get("uiR2EDMacroComponents"):toUtf8(),
21 Prop =
23 {Name="Behavior", Type="LogicEntityBehavior"},
26 ---------------------------------------------------------------------------------------------------------
27 -- from base class
28 getContextualTreeIcon = function(this)
29 if this:getParentAct():isBaseAct() then
30 return this:getPermanentTreeIcon()
31 end
32 return ""
33 end,
35 getSelectBarIcon = function(this)
36 return r2.Classes.BaseClass.getContextualTreeIcon(this)
37 end,
39 ---------------------------------------------------------------------------------------------------------
40 -- from base class
41 getPermanentStatutIcon = function(this)
43 if not this:isBotObject() and this:getParentAct():isBaseAct() then
44 return "r2ed_permanent_pins.tga"
45 else
46 return ""
47 end
48 end ,
50 --------------------------------------------------------------------------------------------
51 -- Get the currently selected sequence, or nil if there's no available sequence
52 getSelectedSequenceIndex = function(this)
53 local activities = this:getBehavior().Activities
54 if activities.Size == 0 then return nil end
55 local index = defaulting(this.User.SelectedSequence, 0)
56 if index >= activities.Size then
57 index = activities.Size - 1
58 end
59 return index
60 end,
61 --------------------------------------------------------------------------------------------
62 -- from WorldObject
63 canChangeDisplayMode = function(this)
64 return true
65 end,
66 ---------------------------------------------------------------------------------------------------------
67 -- get the "Category" for this logic entity (Category entry found in the palette)
68 getCategory = function(this)
69 return this.Category
70 end,
71 ---------------------------------------------------------------------------------------------------------
72 -- get the "Sub-Category" for this logic entity (Category entry found in the palette)
73 getSubCategory = function(this)
74 return this.SubCategory
75 end,
76 --------------------------------------------------------------------------------------------
77 isNextSelectable = function(this)
78 return true
79 end,
80 --------------------------------------------------------------------------------------------
81 -- return the behavior object, depending on wether this npc is grouped or not
82 getBehavior = function(this)
83 if this:isKindOf("NpcGrpFeature") then
84 return this.Components[0].Behavior
85 elseif this:isGrouped() and this.ParentInstance:isKindOf("NpcGrpFeature") then
86 return this.ParentInstance.Components[0].Behavior
87 else
88 return this.Behavior
89 end
90 end,
91 --------------------------------------------------------------------------------------------
92 -- check if that npc is part of a group
93 isGrouped = function(this)
94 if this.User.Grouped == true then return true end
95 if this.ParentInstance then
96 return this.ParentInstance:isKindOf("NpcGrpFeature")
97 end
98 return false
99 end,
102 -- get list of command for display in the toolbar
103 getAvailableCommands = function(this, dest)
104 r2.Classes.WorldObject.getAvailableCommands(this, dest)
105 if not this:isBotObject() and not this:isKindOf("Act") then
106 table.insert(dest, this:buildCommand(this.editActions, "edit_actions", "uiR2EDEditEventsTriggers", "r2ed_edit_events.tga", false))
108 if not this:getParentAct():isBaseAct() then
109 table.insert(dest, this:buildCommand(this.togglePermanentCurrentAct, "permanent_content", "uimR2EDMenuPermanentContent", "r2ed_permanent_content.tga", true))
110 else
111 table.insert(dest, this:buildCommand(this.togglePermanentCurrentAct, "current_content", "uimR2EDMenuCurrentActContent", "r2ed_current_act_content.tga", true))
113 end
114 end,
117 togglePermanentCurrentAct = function(this, noNewAction)
119 local newAct
120 local actionName=""
121 if this:getParentAct():isBaseAct() then
122 newAct = r2:getCurrentAct()
123 actionName = "uiR2EDCurrentActEntityAction"
124 else
125 newAct = r2.Scenario:getBaseAct()
126 actionName = "uiR2EDPermanentEntityAction"
129 local parent = newAct.Features[0]
130 local attr = "Components"
131 local instance = this
132 if not this:isInDefaultFeature() then
133 parent = newAct
134 attr = "Features"
135 end
137 if this:isGrouped() or this:isKindOf("Creature") then
138 instance = this.ParentInstance
141 if noNewAction~=false then
142 r2.requestNewAction(i18n.get(actionName))
144 r2.requestMoveNode(instance.InstanceId, "", -1, parent.InstanceId, attr, -1)
145 end,
148 onPostCreate = function(this)
149 if this.User.DisplayProp and this.User.DisplayProp == 1 then
150 r2:setSelectedInstanceId(this.InstanceId)
151 r2:showProperties(this)
152 this.User.DisplayProp = nil
154 end,
156 editActions = function(this)
158 r2.events:openEditor()
159 end,
160 --------------------------------------------------------------------------------------------
161 -- Test if this entity is a bot object
162 isBotObject = function(this)
163 return false
164 end,
165 --------------------------------------------------------------------------------------------
166 -- Test if thisentity is a plant
167 isPlant = function(this)
168 return false
169 end,
170 --------------------------------------------------------------------------------------------
171 -- from base class
172 onPostHrcMove = function (this)
173 -- if no more in a group, then mark as 'ungrouped'
174 local grouped = false
175 if this.ParentInstance then
176 grouped = this.ParentInstance:isKindOf("NpcGrpFeature")
178 this.User.Grouped = grouped
179 -- force update of the available options
180 --if this == r2:getSelectedInstance() then
181 r2.ContextualCommands:update()
182 --end
183 end,
185 getAiCost = function(this)
186 if this.User.GhostDuplicate then return 0 end
187 return r2.getAiCost(this)
188 end,
190 getStaticObjectCost = function(this)
191 return r2.getStaticObjectCost(this)
192 end,
194 hasScenarioCost = function(this)
195 return true;
196 end,
198 createProtected = function(this)
200 if not r2:checkAiQuota() then return end
202 if this.create then
203 this.create()
205 end,
208 getApplicableActions = function(this)
209 return r2.Classes[this.Class].ApplicableActions
210 end,
212 ----------------------------------------------------------------------------
213 -- add a line to the event sub menu
214 initEventTypeMenu = function(this, subMenu, eventCategory)
216 local class = r2.Classes[this.Class]
217 local eventsTable = {}
218 if eventCategory=="ApplicableActions" then
219 eventsTable = this:getApplicableActions()
220 else
221 eventsTable = class[eventCategory]
224 for k, eventType in pairs(eventsTable) do
225 local endRequest = (r2.events.eventTypeWithValue[eventType]==nil)
227 if not r2.getLogicAttribute(this.Class, eventCategory, eventType) then
228 debugInfo("Error: '"..eventCategory.. "' '" ..eventType .. "' is not defined for class'"..this.Class.."'")
229 assert(r2.getLogicAttribute(this.Class, eventCategory, eventType))
230 end
232 local uc_eventType = ucstring()
233 local menuTitle = r2.getLogicAttribute(this.Class, eventCategory, eventType)
235 local addLine = true
236 if r2.events.memberManagement and this:isKindOf("Npc") and this:isGrouped() and menuTitle.groupIndependant~=true then
237 addLine = false
240 if addLine then
241 uc_eventType:fromUtf8(menuTitle.menu)
242 subMenu:addLine(uc_eventType, "lua",
243 "r2.events:setEventType('".. eventType .."','" .. tostring(endRequest) .. "','" .. eventCategory .. "')", eventType)
247 if table.getn(class[eventCategory])==0 then
248 subMenu:addLine(i18n.get("uiR2EdNoSelelection"), "", "", "")
250 end,
254 function logicEntity:getLogicTranslations()
255 local logicTranslations = {
256 ["ApplicableActions"] = {
257 ["activate"] = { menu=i18n.get( "uiR2AA0Activate" ):toUtf8(),
258 text=i18n.get( "uiR2AA1Activate" ):toUtf8()},
259 ["deactivate"] = { menu=i18n.get( "uiR2AA0Deactivate" ):toUtf8(),
260 text=i18n.get( "uiR2AA1Deactivate" ):toUtf8()},
261 ["trigger"] = { menu=i18n.get( "uiR2AA0Trigger" ):toUtf8(),
262 text=i18n.get( "uiR2AA1Trigger" ):toUtf8()},
264 ["Events"] = {
265 ["activation"] = { menu=i18n.get( "uiR2Event0Activation" ):toUtf8(),
266 text=i18n.get( "uiR2Event1Activation" ):toUtf8()},
267 ["deactivation"] = { menu=i18n.get( "uiR2Event0Deactivation" ):toUtf8(),
268 text=i18n.get( "uiR2Event1Deactivation" ):toUtf8()},
269 ["trigger"] = { menu=i18n.get( "uiR2Event0Trigger" ):toUtf8(),
270 text=i18n.get( "uiR2Event1Trigger" ):toUtf8()},
272 ["Conditions"] = {
273 ["is active"] = { menu=i18n.get( "uiR2Test0Active" ):toUtf8(),
274 text=i18n.get( "uiR2Test1Active" ):toUtf8()},
275 ["is inactive"] = { menu=i18n.get( "uiR2Test0Inactive" ):toUtf8(),
276 text=i18n.get( "uiR2Test1Inactive" ):toUtf8()},
279 return logicTranslations
282 -----------------------------------------
283 --- register the curent Feature to menu
285 --function logicEntity.initLogicEntitiesMenu(this, logicEntityMenu)
287 -- if this.InEventUI == true then
288 -- local name = i18n.get("uiR2ED" .. this.Name)
289 -- local tableInstances = r2.Scenario:getAllInstancesByType(this.Name)
290 -- if table.getn(tableInstances) > 0 then
291 -- logicEntityMenu:addLine(name, "lua", "", this.Name)
292 -- end
293 -- end
294 --end
296 ----------------------------------------------------------------------------
297 -- add a line to the event sub menu
298 --function logicEntity.initLogicEntitiesInstancesMenu(this, subMenu, calledFunction)
300 -- local entitiesTable = r2.Scenario:getAllInstancesByType(this.Name)
301 -- for key, entity in pairs(entitiesTable) do
302 -- local uc_name = ucstring()
303 -- uc_name:fromUtf8(entity.Name)
304 -- subMenu:addLine(uc_name, "lua", calledFunction.."('".. entity.InstanceId .."')", entity.InstanceId)
305 -- end
307 -- if table.getn(entitiesTable)==0 then
308 -- subMenu:addLine(i18n.get("uiR2EdNoSelelection"), "", "", "")
309 -- end
310 --end
312 -----------------------------------------
313 --- register the curent Feature to menu
315 function logicEntity.initLogicEntitiesMenu(this, logicEntityMenu)
316 --debugInfo("####5")
317 if this.InEventUI == true then
318 local name = i18n.get("uiR2ED" .. this.Name)
319 --local startTime = nltime.getPreciseLocalTime()
320 local enumerator = r2:enumInstances(this.Name)
321 --local endTime = nltime.getPreciseLocalTime()
322 --debugInfo(string.format("time for enumInstances is %f", endTime - startTime))
323 startTime = endTime
324 if enumerator:next() then
325 logicEntityMenu:addLine(name, "lua", "", this.Name)
327 --endTime = nltime.getPreciseLocalTime()
328 --debugInfo(string.format("time for next is %f", endTime - startTime))
332 ------------------------------------------------------------------------------
333 ---- add a line to the event sub menu
334 function logicEntity.initLogicEntitiesInstancesMenu(this, subMenu, calledFunction)
335 local enumerator = r2:enumInstances(this.Name)
336 local found = false
337 while 1 do
338 local entity = enumerator:next()
339 if not entity then break end
340 found= true
341 local uc_name = ucstring()
342 uc_name:fromUtf8(entity.Name)
343 subMenu:addLine(uc_name, "lua", calledFunction.."('".. entity.InstanceId .."')", entity.InstanceId)
345 if not found then
346 subMenu:addLine(i18n.get("uiR2EdNoSelelection"), "", "", "")
354 r2.registerComponent(logicEntity)
356 ---------------------------------------------------
357 --useful to represent a mission
358 --an empty group, an active state, a inactive state
359 --and a finished state. Use the createPseudoGroup
360 --function to directly add these in the context
361 --local pseudoGroup=
363 -- BaseClass="BaseClass",
364 -- Name="PseudoGroup",
365 -- Prop=
366 -- {
367 -- {Name="RtGroup",Type="RtNpcGrp"},
368 -- {Name="InactiveState",Type="RtAiState"},
369 -- {Name="ActiveState",Type="RtAiState"},
370 -- {Name="FinishedState",Type="RtAiState"},
371 -- }
373 --r2.registerComponent(pseudoGroup)
375 --insert a new text in the textManager, after it has been translated
376 local insertTextRt = function(text,context)
377 local rtEntry = r2.newComponent("RtEntryText")
378 rtEntry.Text = text
379 debugInfo(colorTag(128,128,0).."insertion : "..text.." "..rtEntry.Id)
380 table.insert(context.RtScenario.Texts.Texts,rtEntry)
381 debugInfo(colorTag(128,128,0).."new size : "..table.getn(context.RtScenario.Texts.Texts))
382 return rtEntry.Id
385 ----------------------------------------------
386 ----create a psudo group to translate missions
387 ----insert the elements in the context
388 --r2.createPseudoGroup = function(context)
389 -- local PseudoGroup = r2.newComponent("PseudoGroup")
390 -- local group = PseudoGroup.RtGroup
391 -- group.Name = group.Id
393 -- table.insert(context.RtAct.NpcGrps, group)
395 -- do
396 -- local state
398 -- state= PseudoGroup.InactiveState
399 -- state.Name = state.Id
400 -- table.insert(context.RtAct.AiStates,state)
401 -- table.insert(state.Children,group.Id)
403 -- state= PseudoGroup.ActiveState
404 -- state.Name = state.Id
405 -- table.insert(context.RtAct.AiStates,state)
408 -- state= PseudoGroup.FinishedState
409 -- state.Name = state.Id
410 -- table.insert(context.RtAct.AiStates,state)
412 -- end
413 -- return PseudoGroup
414 --end
418 local feature = {}
421 --local logicTexts ={
422 -- BaseClass="BaseClass",
423 -- Name="LogicTexts",
424 -- Prop=
425 -- {
426 -- {Name="Spontaneous",Type="Table"},
427 -- {Name="Interrogated",Type="Table"},
428 -- },
431 --local LogicTextsTranslator = function(this,context,logicEntity)
432 -- local addTriggeredAction = r2.Features["ActivitySequence"].addTriggeredAction
433 -- local action
434 -- local index
435 -- local counter =context.Counter
437 -- if logicEntity == nil
438 -- then
439 -- debugInfo("logic entity nil!!")
440 -- end
442 -- if context.RtGroups == nil
443 -- then
444 -- debugInfo("context.RtGroups nil!!")
445 -- end
447 -- if context.RtGroups[logicEntity.NpcGrpId] == nil
448 -- then
449 -- debugInfo("context.RtGroups[logicEntity.NpcGrpId] nil!!")
450 -- end
452 -- for k,v in pairs(this.Spontaneous)
453 -- do
454 -- if k ~= "Keys"
455 -- then
456 -- --get the "npc_say" action
457 -- action = Translator.LogicEntityTranslator(v,context,logicEntity)
458 -- --add this action to the triggerable actions of the npc group which give the mission
459 -- index = addTriggeredAction(context,context.RtGroups[logicEntity.NpcGrpId].Name,action)
461 -- local name = context.RtGroups[logicEntity.NpcGrpId].Name
463 -- --create an action to trigg the action to the npc group
464 -- action = Actions.createAction("modify_variable",name..":v3 = "..index)
466 -- --then, add the action to the correct state/event
468 -- if k=="Activated"
469 -- then
470 -- r2.Utils.addReaction(counter.ActiveState,"start_of_state",action)
471 -- end
473 -- if k=="Deactivated"
474 -- then
475 -- r2.Utils.addReaction(counter.InactiveState,"start_of_state",action)
476 -- end
478 -- if k=="Progresses"
479 -- then
480 -- r2.Utils.addReaction(counter.ActiveState,"user_event_0",action)
481 -- end
482 -- end
483 -- end
485 -- for k,v in pairs(this.Interrogated)
486 -- do
487 -- if k ~= "Keys"
488 -- then
489 -- --get the "npc_say" action
490 -- action = r2.Translator.LogicEntityTranslator(v,context)
491 -- --add this action to the triggerable actions of the npc group which give the mission
492 -- index = addTriggeredAction(context,context.RtGroups[logicEntity.NpcGrpId].Name,action)
493 -- local name = context.RtGroups[logicEntity.NpcGrpId].Name
494 -- --create an action to trigg the action to the npc group
495 -- action = Actions.createAction("modify_variable",name..":v3 = "..index)
497 -- --TODO insert the action in the correct state/event ...
498 -- end
499 -- end
501 --end
503 --r2.registerComponent(logicTexts)
506 --r2.registerComponent(varText)
507 ---------------------------------------------------------
508 --This component is linked to a BaseCounter.It's used in
509 --the ParametrableText component to represent the value
510 --of the variable
511 --local var =
513 -- BaseClass="BaseClass",
514 -- Name="TextParam",
515 -- Prop=
516 -- {
517 -- {Name="BaseCounterId",Type="String"}
518 -- }
520 --r2.registerComponent(var)
523 ----------------------------------------------------
524 --this component represents a text with parameters.
525 --It's a table of strings and/or TextParam elements.
526 --It allows to build sentences with variables.
527 --The Translator build a sentence with the strings
528 -- and parameters, and returns a "npc_say" action.
529 --see the UnitTest.testCounter() function.
530 --local paramText =
532 -- BaseClass="BaseClass",
533 -- Name="ParametrableText",
534 -- Prop=
535 -- {
536 -- --components are : "TextParam" objects or strings
537 -- {Name="Components",Type="Table"},
538 -- {Name="Npc",Type="String"}
539 -- }
542 --r2.registerComponent(paramText)
545 --local ParamTextTranslator = function(this,context)
546 -- local text=""
547 -- local param=""
548 -- for k,v in pairs(this.Components)
549 -- do
550 -- if k~="Keys"
551 -- then
552 -- if type(v) == "string"
553 -- then
554 -- text = text..v
555 -- else
556 -- if v.Class == "TextParam"
557 -- then
558 -- local id = v.BaseCounterId
559 -- local baseCounter = context.Components[id]
560 -- local counterName = context.CounterNames[id]
561 -- param = r2.Utils.concat(param,counterName)
562 -- text = text.."$d "..baseCounter.Object.." "
563 -- end
564 -- end
566 -- end
567 -- end
568 -- local action = r2.newComponent("RtNpcEventHandlerAction")
569 -- action.Action = "npc_say"
570 -- local who = r2.Utils.getNpcParam(this.Npc,context)
571 -- action.Parameters = who.."\n"..insertTextRt(text,context).."\n"..param
572 -- return action
573 --end
575 -- Obsolette?
576 --Translator.LogicEntityTranslator = function(logicEntity,context,ParentLogicEntity)
577 -- local class = logicEntity.Class
578 -- if class == "VarText"
579 -- then
580 -- return VarTextTranslator(logicEntity,context,ParentLogicEntity)
581 -- end
582 -- if class == "Counter"
583 -- then
584 -- return CounterTranslator(logicEntity,context,ParentLogicEntity)
585 -- end
586 -- if class == "LogicTexts"
587 -- then
588 -- return LogicTextsTranslator(logicEntity,context,ParentLogicEntity)
589 -- end
590 -- if class == "BaseCounter"
591 -- then
592 -- return BaseCounterTranslator(logicEntity,context,ParentLogicEntity)
593 -- end
594 -- if class == "ParametrableText"
595 -- then
596 -- return ParamTextTranslator(logicEntity,context)
597 -- end
598 --end