Merge branch 'fixes' into main/gingo-test
[ryzomcore.git] / ryzom / common / data_common / r2 / r2_components.lua
blobfcb68f24b858688815f24a76ef97cbf7a1c333f4
1 r2.registerHighLevel = function()
2 local classMapDescriptionVersion = 0
4 local classMapDescription =
6 BaseClass="BaseClass",
7 Name = "MapDescription",
8 DisplayerUI = "",
9 ersion = classMapDescriptionVersion,
10 Prop =
12 {Name="Title", Type="String", Category="uiR2EDRollout_Scenario"},
13 {Name="LevelId", Type="String"},
14 {Name="ShortDescription", Type="String", Category="uiREDRollout_"},
15 {Name="OptimalNumberOfPlayer", Type="Number", Category="uiREDRollout_", Min="1", Max="10", Default="1"},
16 {Name="Creator", Type="String", Category="uiREDRollout_", WidgetStyle = "StaticText"},
17 {Name="CreatorMD5", Type="String", Category="uiREDRollout_", WidgetStyle = "StaticText"},
19 {Name="CreationDate", Type="String", Category="uiREDRollout_", WidgetStyle = "StaticText"},
20 {Name="OtherCharAccess", Type="String", Category="uiREDRollout_", WidgetStyle = "StaticText", DefaultValue="Full", DefaultInBase = 1 },
21 {Name="NevraxScenario", Type="String", Category="uiREDRollout_", WidgetStyle = "StaticText", DefaultValue="0", DefaultInBase = 1 },
22 {Name="TrialAllowed", Type="String", Category="uiREDRollout_", WidgetStyle = "StaticText", DefaultValue="0", DefaultInBase = 1 },
23 {Name="ScenarioTag", Type="String", Category="uiREDRollout_", WidgetStyle = "StaticText", DefaultValue="", DefaultInBase = 1 },
30 local classScenarioVersionName = getClientCfgVar("BuildName")
31 local classScenarioVersion = 4
33 local classScenario =
35 --BaseClass="BaseClass",
36 BaseClass="LogicEntity",
37 Name = "Scenario",
38 InEventUI = true,
39 Version = classScenarioVersion,
40 VersionName =classScenarioVersionName,
41 BuildPropertySheet = false,
42 Prop =
44 {Name="AccessRules", Type="String", WidgetStyle = "StaticText"},
45 {Name="Description", Type="MapDescription"},
46 {Name="Acts", Type="Table"},
47 {Name="Locations", Type="Table"},
48 {Name="Texts", Type="TextManager"},
49 {Name="VersionName", Type="String", DefaultValue=classScenarioVersionName, Visible=false }, -- just a string
50 {Name="Versions", Type="Table"},
51 {Name="UserComponents", Type="Table"},
52 {Name="PlotItems", Type="Table"},
53 {Name="Language", Type="String", DefaultValue="en", Visible=false},
54 {Name="Type", Type="String", DefaultValue="so_story_telling", Visible=false},
55 --{Name="TestRefId", Type="RefId", Category="uiR2EDRollout_Test"},
56 {Name="ScenarioScore", Type="Number", DefaultValue="0", Min="0", Visible=false},
57 {Name="Score", Type="Number"},
59 Parameters = {},
60 ApplicableActions = {
61 --"Start Scenario Timing", "Stop Scenario Timing", "add scenario points", "succeed scenario", "fail scenario"
63 Events = {
64 -- "on scenario succeeded", "on scenario failed"
66 Conditions = {
67 -- "is active", "is finished"
69 TextContexts = {},
70 TextParameters = {},
71 LiveParameters = {},
72 ----------------------------------------------------------------------------------------------------
73 isDisplayModeOptionAvailable = function(this) return false end,
74 ----------------------------------------------------------------------------------------------------
75 updateVersion = function(this, scenarioValue, currentValue)
76 local patchValue = scenarioValue
77 if patchValue < 1 then
78 -- Patch only for old save (not the 0.0.3)
79 if VersionName ~= "0.0.3" then
80 -- TODO use identifier instead
81 local oldValue = this.Description.LocationId
82 local newValue = oldValue
84 if 0 == oldValue then
85 newValue = 1
86 elseif 1 <= oldValue and oldValue <= 5 then
87 newValue = oldValue + 2
88 elseif 6 == oldValue then
89 newValue = 9
90 elseif 7 == oldValue then
91 newValue = 11
92 elseif 8 <= oldValue and oldValue <= 27 then
93 newValue = oldValue + 5
94 end
96 r2.requestSetNode(this.Description.InstanceId, "LocationId", newValue)
97 end
98 patchValue = 1
99 end
101 -- plot item feature
102 if patchValue < 2 then
103 r2.requestSetNode(this.InstanceId, "PlotItems", {})
104 r2.requestSetNode(this.InstanceId, "UserComponents", {})
105 patchValue = 2
108 -- update of enum for scenario type
109 if patchValue < 3 then
110 if this.Type == nil or this.Type == "" then
111 r2.requestSetNode(this.InstanceId, "Type", "so_story_telling")
112 elseif this.Type == "Roleplay" then
113 r2.requestSetNode(this.InstanceId, "Type", "so_story_telling")
114 elseif this.Type == "Combat" then
115 r2.requestSetNode(this.InstanceId, "Type", "so_hack_slash")
117 patchValue = 3
120 -- patch for level
121 if patchValue < 4 then
122 if this.Description.LevelId == nil or this.Description.LevelId < 0 or this.Description.LevelId > 5 then
123 r2.requestSetNode(this.Description.InstanceId, "LevelId", 0)
124 end
125 patchValue = 4
130 if patchValue == currentValue then return true end
131 return false
132 end,
134 ---------------------------------------------------------------------------------------------------------
135 -- get name of tree icon
136 getContextualTreeIcon = function(this)
137 return this:getTreeIcon()
138 end,
140 -----------------------------------------------------------------------------
141 getBaseAct = function(this)
142 return this.Acts[0]
143 end,
145 getCurrentAct = function(this)
146 return r2:getCurrentAct()
147 end,
148 -----------------------------------------------------------------------------
149 -- from baseClass
150 getDisplayName = function(this)
151 return i18n.get("uiR2EDScenario")
152 end,
153 -----------------------------------------------------------------------------
154 -- from baseClass
155 isDeletable = function(this)
156 return false
157 end,
158 -----------------------------------------------------------------------------
160 getBaseActLeftBudget = function(this)
161 local maxValue = this:getMaxSecondaryActCost()
162 return this.Description.MaxEntities - this:getBaseAct():getLocalCost() - maxValue
163 end,
164 -----------------------------------------------------------------------------
165 -- Called by the C++ just before testing to see if the cost of this scenario is valid
166 -- Should return true in this case
167 -- If the scenario has a too high cost, then this function has the responsability to warn the player
168 validateForTesting = function(this)
169 if this:getMaxSecondaryActCost() < 0 then
170 messageBox(i18n.get("uiR2EDScenarioBudgetExceeded"))
171 return false
172 else
173 return true
175 end,
176 -----------------------------------------------------------------------------
178 getMaxSecondaryActCost = function(this)
179 local scenarioObj = r2.getScenarioObj()
180 local max = 0
181 local maxStatic = 0
182 local first = true
183 k,v = next(this.Acts,nil)
184 while k~=nil do
185 if first == true then
186 first = false
187 else
188 if max < v:getLocalCost() then
189 max = v:getLocalCost()
191 if maxStatic < v:getLocalStaticCost() then
192 debugInfo("setting maxStatic")
193 maxStatic = v:getLocalStaticCost()
196 k,v=next(this.Acts,k)
199 return max, maxStatic
200 end,
201 -----------------------------------------------------------------------------
202 -- returns a table with all objects of kind "kind" in the permanent act & current act
203 getAllInstancesByType = function(this, kind)
204 assert(type(kind) == "string")
205 local result = {}
206 --this:delegate():appendInstancesByType(result, kind)
207 r2.Classes.BaseClass.appendInstancesByType(this, result, kind)
208 this.Acts[0]:appendInstancesByType(result, kind)
209 local currAct = r2:getCurrentAct()
210 if currAct ~= nil and currAct ~= this.Acts[0] then
211 currAct:appendInstancesByType(result, kind)
213 return result
214 end,
215 -----------------------------------------------------------------------------
216 -- from baseClass
217 completeSelectBarMenu = function(this, rootMenu)
218 -- if all acts are not used, propose to create a new one
219 --rootMenu:addSeparator()
220 --r2:addMenuLine(rootMenu, this:getDisplayName(), "lua", "r2:setSelectedInstanceId('" .. this.InstanceId .."')", tostring(k), this:getSelectBarIcon(), 14)
221 --rootMenu:addSeparator()
222 --r2:addMenuLine(rootMenu, i18n.get("uiR2EDNewAct"), "lua", "r2.ScenarioWindow:newAct()", "new_act", "r2_icon_create.tga", 14)
223 end,
224 -----------------------------------------------------------------------------
225 -- from baseClass
226 displayInSelectBar = function(this)
227 return false -- don't display in the selection bar (only acts can be ...)
228 end,
230 ---------------------------------------------------------------------------------------------------------
231 -- from base class
232 getFirstSelectBarSon = function(this)
233 return r2:getCurrentAct():getFirstSelectBarSon()
234 end,
235 ---------------------------------------------------------------------------------------------------------
236 -- from base class
237 canHaveSelectBarSons = function(this)
238 return false;
239 end,
240 ---------------------------------------------------------------------------------------------------------
241 -- from base class, update the item ui on first display
242 onPostCreate = function(this)
243 r2.PlotItemsPanel:reinit()
244 r2.PlotItemDisplayerCommon:touch()
245 if r2.Mode == "Edit" then
246 -- if some element in the scenario are hidden, then display
247 -- a message for the user to remember it
248 -- local sons = {}
249 -- this:getSons(sons)
250 -- local showWarning = false
251 -- for k, v in pairs(sons) do
252 -- if type(v) == "userdata" and v.isKindOf and v:isKindOf("WorldObject") and v.DisplayMode ~= 0 then
253 -- showWarning = true
254 -- break
255 -- end
256 -- end
257 -- if showWarning then
258 -- messageBox(i18n.get("uiR2EDDisplayModeMenuReminder"))
259 -- end
260 -- reset display modes
261 r2.PrimDisplayFrozen = false
262 r2.PrimDisplayVisible = true
263 r2.PrimDisplayContextualVisibility = false
264 r2.BotObjectsFrozen = false
265 r2:setupFreezeBotObjectButton()
266 end
267 end,
269 onAttrModified = function(this, name)
270 if this == r2.Scenario then
271 if name ~= "Acts" then
272 r2.ScenarioWindow:updateScenarioProperties()
275 if name=="Acts" and r2.Scenario:getCurrentAct()==r2.Scenario:getBaseAct() and r2.Scenario.Acts.Size>1 then
276 r2.ScenarioWindow:setAct( r2.Scenario.Acts[1] )
279 end,
281 -----------------------------------------------------------------------------
282 onErase = function(this)
283 r2.acts.deleteOldScenario = false
284 end,
285 getName = function(this)
286 if this.Ghost_Name then return this.Ghost_Name end
287 return this.Name
288 end,
291 ----------------------------------------------------------------------------
292 -- add a line to the event menu
293 function classScenario.initLogicEntitiesMenu(this, logicEntityMenu)
294 local name = i18n.get("uiR2EDScenario")
295 logicEntityMenu:addLine(name, "lua", "", "Scenario")
298 ----------------------------------------------------------------------------
299 -- add a line to the event sub menu
300 function classScenario.initLogicEntitiesInstancesMenu(this, subMenu, calledFunction)
301 local uc_name = ucstring()
302 uc_name:fromUtf8(r2.Scenario:getName())
303 subMenu:addLine(uc_name, "lua", calledFunction.."('".. r2.Scenario.InstanceId .."')", r2.Scenario.InstanceId)
306 ----------------------------------------------------------------------------
307 -- add a line to the event menu
308 function classScenario:getLogicTranslations()
309 local logicTranslations = {
310 ["ApplicableActions"] = {
311 --["Start Scenario Timing"] = { menu=i18n.get( "uiR2AA0ScenarioStartTiming" ):toUtf8(),
312 -- text=i18n.get( "uiR2AA1ScenarioStartTiming" ):toUtf8()},
313 --["Stop Scenario Timing"] = { menu=i18n.get( "uiR2AA0ScenarioStopTiming" ):toUtf8(),
314 -- text=i18n.get( "uiR2AA1ScenarioStopTiming" ):toUtf8()},
315 --["add scenario points"] = { menu=i18n.get( "uiR2AA0ScenarioAddPoints" ):toUtf8(),
316 -- text=i18n.get( "uiR2AA1ScenarioAddPoints" ):toUtf8()},
317 --["succeed scenario"] = { menu=i18n.get( "uiR2AA0ScenarioSucceed" ):toUtf8(),
318 -- text=i18n.get( "uiR2AA1ScenarioSucceed" ):toUtf8()},
319 --["fail scenario"] = { menu=i18n.get( "uiR2AA0ScenarioFail" ):toUtf8(),
320 -- text=i18n.get( "uiR2AA1ScenarioFail" ):toUtf8()},
322 ["Events"] = {
323 --["On Scenario Started"] = { menu=i18n.get( "uiR2Event0ScenarioStart" ):toUtf8(),
324 -- text=i18n.get( "uiR2Event1ScenarioStart" ):toUtf8()},
325 --["on scenario succeeded"] = { menu=i18n.get( "uiR2Event0ScenarioSucceed" ):toUtf8(),
326 -- text=i18n.get( "uiR2Event1ScenarioSucceed" ):toUtf8()},
327 --["on scenario failed"] = { menu=i18n.get( "uiR2Event0ScenarioFailed" ):toUtf8(),
328 -- text=i18n.get( "uiR2Event1ScenarioFailed" ):toUtf8()},
330 ["Conditions"] = {
333 return logicTranslations
336 function classScenario.initEventValuesMenu(this, menu, categoryEvent)
337 for ev=0,menu:getNumLine()-1 do
339 local eventType = tostring(menu:getLineId(ev))
341 if r2.events.eventTypeWithValue[eventType] == "Number" then
342 menu:addSubMenu(ev)
343 local subMenu = menu:getSubMenu(ev)
344 local func = ""
346 local lineNb = 0
347 for i=1, 100, 20 do
348 local lineStr = tostring(i).."/"..tostring(i+19)
349 subMenu:addLine(ucstring(lineStr), "", "", tostring(i))
351 subMenu:addSubMenu(lineNb)
352 local subMenu2= subMenu:getSubMenu(lineNb)
353 for s=0, 19 do
354 lineStr = tostring(i+s)
355 local func = "r2.events:setEventValue('','" .. categoryEvent .."','".. lineStr.."')"
356 subMenu2:addLine(ucstring(lineStr), "lua", func, lineStr)
358 lineNb = lineNb+1
364 function classScenario.pretranslate(this, context)
365 -- Nothing to do: Done by act[0]:pretranslate
368 function classScenario.translate(this, context)
369 r2.Translator.translateAiGroup(this, context)
373 function classScenario.getLogicEvent(this, context, event)
374 assert( event.Class == "LogicEntityAction")
376 local component = this -- r2:getInstanceFromId(event.Entity)
377 assert(component)
378 local rtNpcGrp = r2.Translator.getRtGroup(context, component.InstanceId)
379 assert(rtNpcGrp)
381 local eventType = tostring(event.Event.Type)
383 local eventHandler, firstCondition, lastCondition = nil, nil, nil
385 local rtNpcGrp = r2.Translator.getRtGroup(context, r2.Scenario.Acts[0].InstanceId)
386 assert(rtNpcGrp)
388 if eventType == "On Scenario Started" then
389 return r2.Translator.createEvent("timer_t0_triggered", "", rtNpcGrp.Id)
390 elseif eventType == "on scenario succeeded" then
391 return r2.Translator.getComponentUserEvent(rtNpcGrp, 7)
392 elseif eventType == "on scenario failed" then
393 return r2.Translator.getComponentUserEvent(rtNpcGrp, 8)
396 return eventHandler, firstCondition, lastCondition
399 function classScenario.getLogicAction(entity, context, action)
400 assert( action.Class == "ActionStep")
401 local component = r2:getInstanceFromId(action.Entity)
402 assert(component)
403 local rtNpcGrp = r2.Utils.getRtGroup(context, component.InstanceId)
404 assert(rtNpcGrp)
406 if (action.Action.Type == "Start Scenario Timing") then
407 local action = r2.Translator.createAction("start_scenario_timing")
408 return action, action
409 elseif (action.Action.Type == "Stop Scenario Timing") then
410 local action = r2.Translator.createAction("stop_scenario_timing")
411 return action, action
412 elseif (action.Action.Type == "add scenario points") then
413 if not action.Action.ValueString then return end
414 local points = tonumber(action.Action.ValueString)
415 local baseAct = r2.Scenario:getBaseAct()
416 local rtBaseActGrp = r2.Translator.getRtGroup(context, baseAct.InstanceId)
418 local action = r2.Translator.createAction("add_scenario_points", rtBaseActGrp.Id, points)
419 return action, action
420 elseif action.Action.Type == "succeed scenario" then
421 local action1 = r2.Translator.createAction("set_value", rtNpcGrp.Id, "Success", 1)
422 local action2 = r2.Translator.createAction("user_event_trigger", rtNpcGrp.Id, 7)
423 local retAction = r2.Translator.createAction("multi_actions", {action1, action2})
424 assert(retAction)
425 return retAction, retAction
426 elseif action.Action.Type == "fail scenario" then
427 local action1 = r2.Translator.createAction("set_value", rtNpcGrp.Id, "Success", 0)
428 local action2 = r2.Translator.createAction("user_event_trigger", rtNpcGrp.Id, 8)
429 local retAction = r2.Translator.createAction("multi_actions", {action1, action2})
430 assert(retAction)
431 return retAction, retAction
434 return r2.Translator.getFeatureActivationLogicAction(rtNpcGrp, action)
437 function classScenario.getLogicCondition(this, context, condition)
438 assert( condition.Class == "ConditionStep")
439 local component = r2:getInstanceFromId(condition.Entity)
440 assert(component)
441 local rtNpcGrp = r2.Utils.getRtGroup(context, component.InstanceId)
442 assert(rtNpcGrp)
444 return r2.Translator.getFeatureActivationCondition(condition, rtNpcGrp)
449 function classScenario.getActIndex(this, actInstanceId)
450 local index = 0
451 local k, v = next(this.Acts)
452 while k do
453 if tostring(v.InstanceId) == actInstanceId then
454 return index
456 index = index + 1
457 k, v = next(this.Acts, k)
459 return -1
463 -- maps each season found in the list box season to an enum to pass to setEditorSeason
464 r2.ListBoxSeasonToEditorSeason =
466 [0] = "Automatic",
467 [1] = "Spring",
468 [2] = "Summer",
469 [3] = "Autumn",
470 [4] = "Winter"
474 local classActVersion = 6
476 local classAct =
478 BaseClass="LogicEntity",
479 Name = "Act",
480 InEventUI = true,
481 Menu="ui:interface:r2ed_base_menu",
482 DisplayerUI = "R2::CDisplayerLua",
483 DisplayerUIParams = "createActUIDisplayer",
484 TreeIcon="r2ed_icon_act.tga",
485 Version=classActVersion,
486 Parameters = {},
487 ApplicableActions = {
488 "Start Act",
490 Events = {
491 "On Act Started",
492 --"On Scenario Started",
494 Conditions = {
495 -- "is active", "is finished"
497 TextContexts = {},
498 TextParameters = {},
499 LiveParameters = {},
500 Prop =
502 {Name="Version", Type="Number", Visible=false, DefaultValue=tostring(classActVersion)},
503 {Name="Features", Type="Table"},
504 {Name="Events",Type="Table"},
506 -- following field are tmp for property sheet building testing
507 -- {Name="PVP", Type="Number", WidgetStyle="Boolean", Category="uiR2EDRollout_Test" },
508 -- {Name="Slider1", Type="Number", WidgetStyle="Slider", Category="uiR2EDRollout_Test"},
509 -- {Name="Slider2", Type="Number", WidgetStyle="Slider", Category="uiR2EDRollout_Test"},
510 -- {Name="ComboBox1", Type="Number", WidgetStyle="EnumDropDown",
511 -- Enum= { "Toto", "Tata", "Titi" }
512 --},
513 -- {Name="ComboBox2", Type="Number", WidgetStyle="EnumDropDown",
514 -- Enum= { "A", "B", "C" }
515 -- },
516 {Name="Title", Type="String", WidgetStyle = "StaticText"},
517 {Name="Name", Type="String", MaxNumChar="25"},
520 {Name="ActivitiesIds",Type="Table"},
521 {Name="Counters",Type="Table"},
522 {Name="ManualWeather", Type="Number", WidgetStyle="Boolean", DefaultValue="0",
523 Visible = function(act) return not act:isBaseAct() end,
525 {Name="WeatherValue", Type="Number", WidgetStyle="Slider", Min=0, Max=1022, -- The final value in the Rt datas is 0 for autiweather and 1-1023 for weather value ([1, 1023] range <=> [0, 1022])
526 Visible = function(act) return act.ManualWeather == 1 and not act:isBaseAct() end,
528 {Name="Season", Type="Number", WidgetStyle="EnumDropDown", DefaultValue="0", Visible=false,
529 Enum= { "uiR2EDSeasonAuto", "uiR2EDSpring", "uiR2EDSummer", "uiR2EDAutumn", "uiR2EDWinter" },
531 {Name="LocationId", Type="String", Visible=false},
532 {Name="ShortDescription", Type="String", Visible=false},
533 {Name="PreActDescription", Type="String", DefaultValue="", Visible=false, DefaultInBase=1},
536 updateVersion = function(this, scenarioValue, currentValue )
537 local patchValue = scenarioValue
538 if patchValue < 1 then
539 r2.requestSetNode(this.InstanceId, "ManualWeather", 0)
540 r2.requestSetNode(this.InstanceId, "WeatherValue", 0)
541 patchValue = 1
544 if patchValue < 2 then
545 if not this.Behavior then
546 local behavior = r2.newComponent("LogicEntityBehavior")
547 r2.requestInsertNode(this.InstanceId, "", -1, "Behavior", behavior)
548 r2.requestSetNode(this.InstanceId, "InheritPos", 1)
549 -- TODO Add position (0,0,0)
551 patchValue = 2
554 if patchValue < 3 then
555 if not this.Name then
556 r2.requestSetNode(this.InstanceId, "Name", this.Title)
558 patchValue = 3
560 if patchValue < 4 then
561 if not this.ExportList then
562 -- r2.requestInsertNode(this.InstanceId, "", -1, "ExportList", {})
564 patchValue = 4
566 -- version 5 : Remove the "Cost" field -> hold locally now
567 if patchValue < 5 then
568 if this.Cost then
569 r2.requestEraseNode(this.InstanceId, "Cost", -1)
571 if this.StaticCost then
572 r2.requestEraseNode(this.InstanceId, "StaticCost", -1)
574 patchValue = 5
577 if patchValue < 6 then
578 if this.ExportList then
579 r2.requestEraseNode(this.InstanceId, "ExportList", -1)
581 patchValue = 6
584 if patchValue == currentValue then return true end
585 return false
586 end,
587 -----------------------------------------------------------------------------
588 canChangeDisplayMode = function(this)
589 return false
590 end,
591 -----------------------------------------------------------------------------
592 onActChanged = function(this)
593 assert(this)
594 if this == r2:getCurrentAct() then
595 r2.acts:updatePaletteFromEcosystem()
596 r2.ScenarioWindow:updateActProperties()
598 end,
599 -----------------------------------------------------------------------------
600 onAttrModified = function(this, name)
601 if name == "Features" or Name == "Events" then
602 -- ignore messages triggeered by sons for the update of the property window
603 return
605 r2.ScenarioWindow:updateActProperties()
606 end,
607 -----------------------------------------------------------------------------
608 onErase = function(this)
610 this.User.Deleted = true
612 if this.User.DeleteInProgress == true then return end
614 this.User.DeleteInProgress = true
615 this:setDeleteActionName()
616 -- assume than on delete can only be called if this act is selected
617 --assert(this:isSameObjectThan(r2:getCurrentAct()))
619 -- update name of acts in act combo box
620 local afterDeletedAct = false
621 for i=0, r2.Scenario.Acts.Size-1 do
622 local act = r2.Scenario.Acts[i]
623 if afterDeletedAct then
624 r2.ActUIDisplayer:updateActName(act)
625 elseif act==this then
626 afterDeletedAct = true
630 -- if Act[1] exists go to act1
631 if not r2.acts.deleteOldScenario then
632 if (table.getn(r2.Scenario.Acts) > 1) and (this~=r2.Scenario.Acts[1]) then
633 r2.ScenarioWindow:setAct( r2.Scenario.Acts[1] )
634 else
635 r2:setCurrentActFromId(r2.Scenario:getBaseAct().InstanceId)
637 if r2.logicComponents.undoRedoInstances[this.InstanceId] and (table.getn(r2.Scenario.Acts) <= 2) then
638 r2.acts:openScenarioActEditor(false, true, true)
643 if r2.logicComponents.undoRedoInstances[this.InstanceId] then
644 r2.logicComponents.undoRedoInstances[this.InstanceId] = nil
645 end
646 end,
648 -----------------------------------------------------------------------------
649 updateWeather = function(this)
650 if this==r2:getCurrentAct() and this.WeatherValue and this.ManualWeather then
651 setWeatherValue(this.ManualWeather == 0, this.WeatherValue / 1022)
653 end,
654 -----------------------------------------------------------------------------
655 accept = function(this, targetInstance)
656 if targetInstance:isKindOf("BanditCampFeature") then
657 return "Features"
658 else
659 return nil
660 end
661 end,
662 getSelectBarIcon = function(this)
663 return "r2ed_icon_act.tga"
664 end,
665 -----------------------------------------------------------------------------
666 isBaseAct = function(this)
667 local parentScenario = this:getParentScenario()
668 if not parentScenario then return false end
669 return this:isSameObjectThan(parentScenario:getBaseAct())
670 --return this == this:getParentScenario():getBaseAct()
671 end,
673 -----------------------------------------------------------------------------
674 -- get the tree control where object other than botobject are inserted in this act
675 getContentTree = function(this)
676 return this.User.ContentTree
677 end,
679 -----------------------------------------------------------------------------
680 -- get the tree control where macro components are inserted in this act
681 getMacroContentTree = function(this)
682 return this.User.MacroContentTree
683 end,
685 -----------------------------------------------------------------------------
686 -- get the tree control where object other than botobject are inserted in this act
687 getContentTreeNodes = function(this, nodeName)
689 local nodes = {}
690 if this:isBaseAct() then
691 local acts = this.Parent
692 if acts.Size>1 then
693 for i=1, acts.Size-1 do
694 if acts[i]:getContentTree() then
695 local node
696 if nodeName then
697 node = acts[i]:getContentTree():getRootNode():getNodeFromId(nodeName)
698 else
699 node = acts[i]:getMacroContentTree():getRootNode()
701 nodes[acts[i].InstanceId] = node
702 else
703 return nil
707 else
708 local node
709 if nodeName then
710 node = this:getContentTree():getRootNode():getNodeFromId(nodeName)
711 else
712 node = this:getMacroContentTree():getRootNode()
714 nodes[this.InstanceId] = node
715 end
716 return nodes
717 end,
719 -----------------------------------------------------------------------------
720 -- get the default feature for this act
721 getDefaultFeature = function(this)
722 assert(this.Features[0]:isKindOf("DefaultFeature"))
723 return this.Features[0]
724 end,
725 -----------------------------------------------------------------------------
726 hasScenarioCost = function(this)
727 return true
728 end,
730 getName = function(this)
731 assert(this)
733 local name = this.Name
734 local actNb = r2.logicComponents:searchElementIndex(this)-1
736 local firstPart = i18n.get("uiR2EDDefaultActTitle"):toUtf8().. actNb
737 local firstPartSpace = i18n.get("uiR2EDDefaultActTitle"):toUtf8().. " " .. actNb
738 if name=="" then
739 name = firstPartSpace
740 elseif string.lower(name)==string.lower(firstPart) or string.lower(name)==string.lower(firstPartSpace) then
741 else
742 name = firstPartSpace .. ":" .. name
745 return name
746 end,
747 setName = function(this, value)
748 assert(this)
749 this.Name = value
750 end,
751 -----------------------------------------------------------------------------
752 -- from baseClass
753 getDisplayName = function(this)
754 if this:isBaseAct() then
755 return i18n.get("uiR2EDBaseAct")
757 local result = ucstring()
758 result:fromUtf8(this:getName())
759 return result
760 end,
761 -----------------------------------------------------------------------------
762 -- from baseClass
763 isDeletable = function(this)
764 return not this:isBaseAct()
765 end,
766 ---------------------------------------------------------------------------------------------------------
767 -- called when the instance is selected (default is no op)
768 onSelect = function(this, selected)
769 if selected and this ~= r2:getCurrentAct() then
770 -- act was changed from the select bar, update editor state
771 r2.ScenarioWindow:setAct(this)
773 end,
774 ---------------------------------------------------------------------------------------------------------
775 -- from baseClass :
776 -- special : the scenario is not displayed in the select bar, but serves as a 'root' for enumeration so
777 -- we return it when acts menu is popped in the selectbar, so that acts can be enumerated
778 getFirstSelectBarParent = function(this)
779 return this.ParentInstance
780 end,
781 ---------------------------------------------------------------------------------------------------------
782 -- from baseClass :
783 getSelectBarSons = function(this)
784 return this.Features
785 end,
787 ---------------------------------------------------------------------------------------------------------
788 -- from BaseClass
789 getParentAct = function(this)
790 return this
791 end
794 function classAct.getActivitiesIds(this)
795 local actActivitiesIds = {}
796 local k, v = next(this.Features, nil)
797 while k do
798 local activitiesIds = {}
799 if v.getActivitiesIds then
800 activitiesIds = v:getActivitiesIds()
801 table.merge(actActivitiesIds, activitiesIds)
803 k, v = next(this.Features, k)
805 return actActivitiesIds
808 function classAct.getWorldPos(this)
809 return { x = 0, y = 0, z = 0 }
812 ----------------------------------------------------------------------------
813 -- add a line to the event sub menu
814 function classAct.initLogicEntitiesInstancesMenu(this, subMenu, calledFunction)
816 local empty = true
817 local actsTable = r2.Scenario.Acts
819 for i=0, r2.Scenario.Acts.Size-1 do
820 local act = r2.Scenario.Acts[i]
821 if not act:isBaseAct() then
822 local uc_name = ucstring()
823 uc_name:fromUtf8(act.Name)
824 subMenu:addLine(uc_name, "lua", calledFunction.."('".. act.InstanceId .."')", act.InstanceId)
825 empty = false
829 if empty==true then
830 subMenu:addLine(i18n.get("uiR2EdNoSelelection"), "", "", "")
834 ----------------------------------------------------------------------------
835 -- add a line to the event menu
836 function classAct:getLogicTranslations()
837 local logicTranslations = {
838 ["ApplicableActions"] = {
839 ["Start Act"] = { menu=i18n.get( "uiR2AA0ActStart" ):toUtf8(),
840 text=i18n.get( "uiR2AA1ActStart" ):toUtf8()},
842 ["Events"] = {
843 ["On Act Started"] = { menu=i18n.get( "uiR2Event0ActStart" ):toUtf8(),
844 text=i18n.get( "uiR2Event1ActStart" ):toUtf8()},
846 ["Conditions"] = {
849 return logicTranslations
852 -----------------------------------------------------------------------------
853 -- eval the used quota for this act alone
854 function classAct.getUsedQuota(this)
855 return this:getLocalCost()
856 end
858 -----------------------------------------------------------------------------
859 function classAct.appendInstancesByType(this, destTable, kind)
860 assert(type(kind) == "string")
861 --this:delegate():appendInstancesByType(destTable, kind)
862 r2.Classes.BaseClass.appendInstancesByType(this, destTable, kind)
863 for key, feature in specPairs(this.Features) do
864 feature:appendInstancesByType(destTable, kind)
867 -----------------------------------------------------------------------------
868 function classAct.onDelete(this)
869 if this.User.DeleteInProgress == true then return end
871 -- assume than on delete can only be called if this act is selected
872 assert(this:isSameObjectThan(r2:getCurrentAct()))
874 r2.ScenarioWindow:deleteAct()
877 -----------------------------------------------------------------------------
878 -- return the left quota to add content into this act
879 function classAct.getLeftQuota(this)
880 if this:isBaseAct()
881 then
882 local maxValue, maxValue2 = this:getParentScenario():getMaxSecondaryActCost()
883 local leftQuota = r2.getMaxNpcs() - this:getLocalCost() - maxValue
884 local leftStaticQuota = r2.getMaxStaticObjects() - this:getLocalStaticCost() - maxValue2
886 return leftQuota, leftStaticQuota
887 else
888 --return this:getParentScenario().Description.MaxEntities - this:getParentScenario():getBaseAct().Cost - this.Cost
889 local cost = r2.getMaxNpcs() - this:getParentScenario():getBaseAct():getLocalCost() - this:getLocalCost()
890 local staticCost = r2.getMaxStaticObjects() - this:getParentScenario():getBaseAct():getLocalStaticCost() - this:getLocalStaticCost()
892 return cost, staticCost
896 function classAct.getActId(this)
897 assert(this)
898 local parent = this:getParentScenario()
899 local id = -1;
900 local k,v = next(parent.Acts, nil)
901 while k do
902 id = id + 1
903 if this:isSameObjectThan(v) then
904 return id
906 k,v = next(parent.Acts, k)
908 return id -- -1
912 function classAct.getLogicAction(entity, context, action)
914 assert( action.Class == "ActionStep")
915 local component = r2:getInstanceFromId(action.Entity)
916 assert(component)
917 local rtNpcGrp = r2.Translator.getRtGroup(context, component.InstanceId)
918 assert(rtNpcGrp)
919 local firstAction, lastAction = nil, nil
920 if action.Action.Type == "Start Act" then
921 firstAction, lastAction = r2.Translator.createAction("dssStartAct", entity:getActId())
922 assert(firstAction)
923 assert(lastAction)
926 return firstAction, lastAction
930 function classAct.getLogicEvent(this, context, event)
931 assert( event.Class == "LogicEntityAction")
933 local component = this -- r2:getInstanceFromId(event.Entity)
934 assert(component)
935 local rtNpcGrp = r2.Translator.getRtGroup(context, component.InstanceId)
936 assert(rtNpcGrp)
938 local eventType = tostring(event.Event.Type)
940 local eventHandler, lastCondition = nil, nil
942 if eventType == "On Act Started" then
943 return r2.Translator.createEvent("timer_t0_triggered", "", rtNpcGrp.Id)
947 return eventHandler, firstCondition, lastCondition
950 function classAct.getLogicCondition(this, context, condition)
951 return nil
955 ----------------------------------------------------------------------------
956 -- Create a controler for the current Act
958 function classAct.pretranslate(this, context)
959 r2.Translator.createAiGroup(this, context)
962 function classAct.translate(this, context)
963 entity = this
965 if this:isBaseAct() then
966 local baseAct = this:getParentScenario():getBaseAct()
967 local rtNpcGrpBase = r2.Translator.getRtGroup(context, baseAct.InstanceId)
968 local rtAction = r2.Translator.createAction("set_scenario_points", rtNpcGrpBase.Id )
970 r2.Translator.translateAiGroupEvent("timer_t1_triggered", this, context, rtAction)
974 if not this:isBaseAct() then
975 r2.Translator.translateAiGroup(entity, context)
976 local rtNpcGrp = r2.Translator.getRtGroup(context, entity.InstanceId)
977 local baseAct = this:getParentScenario():getBaseAct()
978 local rtNpcGrpBase = r2.Translator.getRtGroup(context, baseAct.InstanceId)
979 local index = context.Scenario:getActIndex(this.InstanceId)
981 local rtAction = r2.Translator.createAction("act_starts", rtNpcGrp.Id, rtNpcGrpBase.Id, index)
982 r2.Translator.translateAiGroupInitialState(entity, context, rtAction)
986 local classLocationVersion = 1
987 local classLocation =
989 Version = classLocationVersion,
990 BaseClass="BaseClass",
991 Name = "Location",
992 Prop =
994 {Name="IslandName", Type="String"},
995 {Name="ShortDescription", Type="String"},
996 {Name="Time", Type="Number"},
997 {Name="EntryPoint", Type="String"},
998 {Name="Season", Type="String", DefaultValue=""},
999 {Name="ManualSeason", Type="Number", WidgetStyle="Boolean", DefaultValue="0" },
1002 onCreate = function(this)
1003 this:updateSeason()
1004 end,
1006 onAttrModified = function(this, name)
1007 if not r2:getCurrentAct() then return end
1008 if this.InstanceId == r2:getCurrentAct().LocationId then
1009 if name == "Season" then
1010 this:updateSeason()
1014 end,
1016 updateSeason = function(this)
1018 -- change season in the editor
1019 -- effect may be seen only at the next teleport message if we're joining a session
1020 local season = this.Season
1021 if this.ManualSeason == 0 then season="Automatic" end
1022 --inspect(season)
1023 r2:setEditorSeason(season)
1024 end,
1026 updateVersion = function(this, scenarioValue, currentValue )
1027 local patchValue = scenarioValue
1028 if patchValue < 1 then
1029 local updateMap = { ["summer"] = "Summer", ["winter"] = "Winter", ["fall"] = "Autumn", ["spring"] = "Spring",
1030 ["Summer"] = "Summer", ["Winter"] = "Winter", ["Autumn"] = "Autumn", ["Spring"] = "Spring"}
1031 if (this.ManualSeason == 1 ) then
1032 if updateMap[ this.Season ] then
1033 r2.requestSetNode(this.InstanceId, "Season", updateMap[this.Season])
1034 else
1035 debugInfo("Wrong conversion function")
1036 assert(nil);
1039 patchValue = 1
1040 end
1041 if patchValue == currentValue then return true end
1042 return false
1043 end,
1047 local classState =
1049 Name="State",
1050 Prop=
1052 {Name="InstanceId", Type="String"},
1053 {Name="Name", Type="String" },
1054 {Name="Behavior",Type="Behavior"}
1058 r2.registerComponent(classMapDescription)
1059 r2.registerComponent(classScenario)
1060 r2.registerComponent(classAct)
1061 r2.registerComponent(classState)
1062 r2.registerComponent(classLocation)
1068 --r2.Features.Act = {}
1070 --local feature = r2.Features.Act
1072 --function mergeTraduction(localLogicEntityAttributes)
1073 -- local k, v = next(localLogicEntityAttributes, nil)
1074 -- while k do
1075 -- local k2, v2 = next(v, nil)
1076 -- while k2 do
1077 -- if not r2.logicEntityAttributes[k][k2] then
1078 -- r2.logicEntityAttributes[k][k2] = v2
1079 -- end
1080 -- k2, v2 = next(v, k2)
1081 -- end
1082 -- k, v = next(localLogicEntityAttributes, k)
1083 -- end
1084 --end
1087 --function feature:init()
1088 -- -- register trad
1089 -- local localLogicEntityAttributes = {
1090 -- ["ApplicableActions"] = {
1091 -- ["Start Act"] = i18n.get("uiR2EdStartAct"):toUtf8(),
1092 -- },
1093 -- ["Events"] = {
1094 -- ["On Act Started"] = i18n.get("uiR2EdOnActStarted"):toUtf8(),
1095 -- },
1096 -- ["Conditions"] = {
1097 -- }
1098 -- }
1099 -- mergeTraduction(localLogicEntityAttributes)
1100 --end
1102 --feature.init()
1104 --r2.Features["Act"] = feature
1107 -----------------------------------------------
1108 -- Not Save to disc so not version number needed
1110 r2.registerBasicBricks=function()
1111 local classRtScenario =
1113 Name = "RtScenario",
1114 Prop =
1116 {Name="Acts", Type="Table"},
1117 {Name="Texts", Type="RtTextManager"},
1118 {Name="PlotItems", Type="Table"},
1119 {Name="Locations", Type="Table"}
1123 r2.registerComponent(classRtScenario)
1125 local classRtAct =
1127 Name="RtAct",
1128 Prop=
1130 {Name="Id", Type="String"},
1131 {Name="NpcGrps", Type="Table"},
1132 {Name="FaunaGrps", Type="Table"},
1133 {Name="AiStates", Type="Table"},
1134 {Name="Npcs", Type="Table"},
1135 {Name="Events",Type="Table"},
1136 {Name="Actions", Type="Table"},
1137 {Name="WeatherValue", Type="Number"},
1138 {Name="Name", Type="String"},
1139 {Name="IslandName", Type="String"},
1140 {Name="Season", Type="Number"},
1141 {Name="LocationId", Type="Number"},
1142 {Name="UserTriggers", Type="Table"}
1145 r2.registerComponent(classRtAct)
1147 local classRtLocation =
1149 Name="RtLocation",
1150 Prop=
1152 {Name="Id", Type="String"},
1153 {Name="Island", Type="String"},
1154 {Name="EntryPoint", Type="String"},
1155 {Name="Season", Type="Number"},
1158 r2.registerComponent(classRtLocation)
1161 local classRt =
1163 Name="RtUserTrigger",
1164 Prop=
1166 {Name="Id", Type="String"},
1167 {Name="Name", Type="String"},
1168 {Name="Grp", Type="String"},
1169 {Name="TriggerId", Type="Number"},
1172 r2.registerComponent(classRt)
1176 local classRtNpcGrp =
1178 Name = "RtNpcGrp",
1179 Prop =
1181 {Name="Id", Type="String"},
1182 {Name="Name", Type="String"},
1183 {Name="Children", Type="Table"},
1184 {Name="AutoSpawn", Type="Number", DefaultValue="1"},
1185 {Name="BotChat_parameters", Type="String"},
1186 {Name="BotEquipment", Type="String"},
1187 {Name="BotSheetClient", Type="String"},
1188 {Name="BotVerticalPos", Type="String", DefaultValue="auto"},
1189 {Name="Count", Type="Number"},
1190 {Name="GrpKeywords", Type="String"},
1191 {Name="AiProfilParams", Type="String"},
1192 {Name="GrpParameters", Type="String"},
1198 r2.registerComponent(classRtNpcGrp)
1200 local classRtNpc =
1202 Name = "RtNpc",
1203 Prop =
1205 {Name="Id", Type="String", DefaultValue="" },
1206 {Name="Name", Type="String" },
1207 {Name="Children", Type="Table" },
1208 {Name="ChatParameters", Type="String" },
1209 {Name="Equipment", Type="Table" },
1210 {Name="IsStuck", Type="Number" },
1211 {Name="Keywords", Type="String" },
1212 {Name="Sheet", Type="String" },
1213 {Name="SheetClient", Type="String" },
1214 {Name="BotVerticalPos", Type="String", DefaultValue="auto" },
1215 {Name="Angle", Type="Number" },
1216 {Name="DmProperty", Type="Number"},
1217 {Name="Pt", Type="RtPosition" },
1221 r2.registerComponent(classRtNpc)
1223 local classRtPosition =
1225 Name = "RtPosition",
1226 Prop =
1228 {Name="x", Type="Number" },
1229 {Name="y", Type="Number" },
1230 {Name="z", Type="Number" },
1234 r2.registerComponent(classRtPosition)
1239 local classRtAiState =
1241 Name = "RtAiState",
1242 Prop =
1244 {Name="Id", Type="String", DefaultValue="" },
1245 {Name="Name", Type="String" },
1246 {Name="Children", Type="Table" },
1247 {Name="AiActivity", Type="String", DefaultValue="no_change" },
1248 {Name="AiMovement", Type="String", DefaultValue="" },
1249 {Name="AiProfileParams", Type="Number" },
1250 {Name="Keywords", Type="String" },
1251 {Name="VerticalPos", Type="String", DefaultValue="auto" },
1252 {Name="Pts", Type="Table" },
1253 {Name="Reactions",Type="Table"}
1259 r2.registerComponent(classRtAiState)
1261 local classRtNpcEventHandler =
1263 Name = "RtNpcEventHandler",
1264 Prop =
1266 {Name="Id", Type="String", DefaultValue="" },
1267 {Name="Name",Type="String"},
1268 {Name="Event", Type="String"},
1269 {Name="StatesByName",Type="String"},
1270 {Name="GroupsByName",Type="String"},
1271 {Name="ActionsId", Type="Table"}
1275 r2.registerComponent(classRtNpcEventHandler)
1277 local classRtNpcEventHandlerAction =
1279 Name = "RtNpcEventHandlerAction",
1280 Prop =
1282 {Name="Id", Type="String", DefaultValue="" },
1283 {Name="Action", Type="String"},
1284 {Name="Name", Type="String"},
1285 {Name="Parameters", Type="String"},
1286 {Name="Children",Type="Table"},
1287 {Name="Weight",Type="Number",DefaultValue="1"}
1291 r2.registerComponent(classRtNpcEventHandlerAction)
1293 local classRtFauna =
1295 Name= "RtFauna",
1296 Prop=
1298 {Name="Id", Type="String", DefaultValue=""},
1299 {Name="Name",Type="String"},
1300 {Name="Pts", Type="Table" },
1301 {Name="Children", Type="Table"}
1304 r2.registerComponent(classRtFauna)
1306 local classRtGroupFaunaEx =
1308 Name="RtGroupFaunaEx",
1309 Prop=
1311 {Name="Id",Type="String",DefaultValue=""},
1312 {Name="Name",Type="String"},
1313 {Name="FaunaType",Type="String",DefaultValue="HERBIVORE"},
1314 {Name="Children", Type="Table"}
1317 r2.registerComponent(classRtGroupFaunaEx)
1320 local classRtFaunaGenericPlace =
1322 Name="RtFaunaGenericPlace",
1323 Prop=
1325 {Name="Id",Type="String",DefaultValue=""},
1326 {Name="Name",Type="String"},
1327 {Name="FlagFood",Type="String",DefaultValue="true"},
1328 {Name="FlagRest",Type="String",DefaultValue="true"},
1329 {Name="FlagSpawn",Type="String",DefaultValue="true"},
1330 {Name="Index",Type="Number"},
1331 {Name="IndexNext",Type="Table"},
1332 {Name="Place",Type="Place"}
1335 r2.registerComponent(classRtFaunaGenericPlace)
1337 local classRtPopulation =
1339 Name = "RtPopulation",
1340 Prop=
1342 {Name="Id",Type="String",DefaultValue=""},
1343 {Name="Name",Type="String"},
1344 {Name="Children",Type="Table"}
1347 r2.registerComponent(classRtPopulation)
1349 local classRtPeople =
1351 Name="RtPeople",
1352 Prop=
1354 {Name="Name",Type="String"},
1355 {Name="Count",Type="Number"},
1356 {Name="CreatureCode",Type="String"}
1359 r2.registerComponent(classRtPeople)
1361 local classRtTextManager =
1363 Name="RtTextManager",
1364 Prop=
1366 {Name="Id", Type="String"},
1367 {Name="Texts", Type="Table"},
1371 r2.registerComponent(classRtTextManager)
1373 local classRtEntryText =
1375 Name="RtEntryText",
1376 Prop=
1378 {Name="Id", Type="String"},
1379 {Name="Text", Type="String"}
1383 r2.registerComponent(classRtEntryText)
1386 -- Copy struct TMissionItem
1387 local classRtPlotItem =
1389 Name = "RtPlotItem",
1390 Prop =
1392 {Name="Id", Type="String"},
1393 { Name="SheetId", Type="Number" },
1394 { Name="Name", Type="String" },
1395 { Name="Description", Type="String" },
1396 { Name="Comment", Type="String" }
1399 r2.registerComponent(classRtPlotItem)