Merge branch 'fixes' into main/gingo-test
[ryzomcore.git] / ryzom / common / data_common / r2 / r2_features_default.lua
blob70d12938039a2515b331d63984ed95d9fa6f48da
1 local registerFeature = function ()
2 local feature={}
4 feature.Name="DefaultFeature"
6 feature.Description="The default feature"
8 feature.Components=
10 ActiveLogicEntity = {
11 Name="ActiveLogicEntity",
12 BaseClass="LogicEntity",
13 DisplayerVisual = "R2::CDisplayerVisualEntity",
14 DisplayerVisualParams = { InheritDisplayMode = true },
15 DisplayerUI = "R2::CDisplayerLua",
16 DisplayerUIParams = "defaultUIDisplayer",
17 DisplayerProperties = "R2::CDisplayerLua",
18 DisplayerPropertiesParams = "activeLogicEntityPropertySheetDisplayer",
19 Menu="ui:interface:r2ed_entity_menu",
21 Prop=
23 {Name="Behavior", Type="Behavior"},
24 {Name="ActivitiesId",Type="Table" },
26 isNextSelectable = function(this)
27 return true
28 end,
29 ---------------------------------------------------------------------------------------------------------
30 -- get list of command for display in the mini toolbar
31 getAvailableMiniCommands = function(this, result)
32 -- OBSOLETE
33 --local result = this:delegate():getAvailableMiniCommands(this)
34 r2.Classes.LogicEntity.getAvailableMiniCommands(this, result)
35 end,
36 --------------------------------------------------------------------------------------------
37 -- Test if this entity is a bot object
38 isBotObject = function(this)
39 return false
40 end,
41 --------------------------------------------------------------------------------------------
42 -- Test if thisentity is a plant
43 isPlant = function(this)
44 return false
45 end,
46 --------------------------------------------------------------------------------------------
47 -- is it a named entity ?
48 isNamed = function(this)
49 if this.IsNamed and this.IsNamed == 1 then return true end
50 return false
51 end,
52 --------------------------------------------------------------------------------------------
53 addPrimitiveActivities = function (this, dest, activityWnd)
54 if activityWnd then
55 table.insert(dest, "Wander")
56 table.insert(dest, "Follow Route")
57 table.insert(dest, "Patrol")
58 table.insert(dest, "Repeat Road")
59 table.insert(dest, "Stand Still")
60 else
61 table.insert(dest, this:buildActivityCommand(this.onPickWanderZone, "wander_zone", "uimR2EDMenuPickZone", "r2_toolbar_wander_zone.tga", true))
62 table.insert(dest, this:buildActivityCommand(this.onPickFollowRoute, "follow_route", "uimR2EDMenuFollowRoute", "r2_toolbar_follow_road.tga", false))
63 table.insert(dest, this:buildActivityCommand(this.onPickPatrolRoute, "patrol_route", "uimR2EDMenuPatrolRoute", "r2_toolbar_patrol_road.tga", false))
64 table.insert(dest, this:buildActivityCommand(this.onPickRepeatRoute, "repeat_route", "uimR2EDMenuRepeatRoute", "r2_toolbar_repeat_road.tga", false))
65 table.insert(dest, this:buildActivityCommand(this.onStandStill, "stand_still", "uimR2EDMenuStandInPlace", "r2_toolbar_stand_still.tga", false))
66 end
67 end,
69 -- from 'BaseClass'
70 getAvailableCommands = function(this, dest, activityWnd)
72 --local result = this:delegate():getAvailableCommands(this)
73 if not activityWnd then
74 r2.Classes.LogicEntity.getAvailableCommands(this, dest)
75 end
76 local category = this:getCategory()
78 if category == "Herbivore" then
79 if this:isNamed() then
81 if activityWnd then
82 table.insert(dest, "Guard Zone")
83 table.insert(dest, "Follow Route")
84 table.insert(dest, "Patrol")
85 table.insert(dest, "Repeat Road")
86 table.insert(dest, "Stand Still")
87 else
88 table.insert(dest, this:buildActivityCommand(this.onPickGuardZone, "guard_zone", "uimR2EDMenuPickGuardZone", "r2ed_toolbar_guard_zone.tga", true))
89 table.insert(dest, this:buildActivityCommand(this.onPickFollowRoute, "follow_route", "uimR2EDMenuFollowRoute", "r2_toolbar_follow_road.tga", false))
90 table.insert(dest, this:buildActivityCommand(this.onPickPatrolRoute, "patrol_route", "uimR2EDMenuPatrolRoute", "r2_toolbar_patrol_road.tga", false))
91 table.insert(dest, this:buildActivityCommand(this.onPickRepeatRoute, "repeat_route", "uimR2EDMenuRepeatRoute", "r2_toolbar_repeat_road.tga", false))
92 table.insert(dest, this:buildActivityCommand(this.onStandStill, "stand_still", "uimR2EDMenuStandInPlace", "r2_toolbar_stand_still.tga", false))
93 end
94 else
96 if activityWnd then
97 table.insert(dest, "Rest In Zone")
98 table.insert(dest, "Feed In Zone")
99 else
100 table.insert(dest, this:buildActivityCommand(this.onPickRestZone, "rest_zone", "uimR2EDMenuPickRestZone", "r2ed_toolbar_rest_zone.tga", true))
101 table.insert(dest, this:buildActivityCommand(this.onPickFeedZone, "feed_zone", "uimR2EDMenuPickFeedZone", "r2ed_toolbar_feed_zone.tga", false))
104 elseif category == "Carnivore" then
105 if this:isNamed() then
107 if activityWnd then
108 table.insert(dest, "Guard Zone")
109 table.insert(dest, "Follow Route")
110 table.insert(dest, "Patrol")
111 table.insert(dest, "Repeat Road")
112 table.insert(dest, "Stand Still")
113 else
114 table.insert(dest, this:buildActivityCommand(this.onPickGuardZone, "guard_zone", "uimR2EDMenuPickGuardZone", "r2ed_toolbar_guard_zone.tga", true))
115 table.insert(dest, this:buildActivityCommand(this.onPickFollowRoute, "follow_route", "uimR2EDMenuFollowRoute", "r2_toolbar_follow_road.tga", false))
116 table.insert(dest, this:buildActivityCommand(this.onPickPatrolRoute, "patrol_route", "uimR2EDMenuPatrolRoute", "r2_toolbar_patrol_road.tga", false))
117 table.insert(dest, this:buildActivityCommand(this.onPickRepeatRoute, "repeat_route", "uimR2EDMenuRepeatRoute", "r2_toolbar_repeat_road.tga", false))
118 table.insert(dest, this:buildActivityCommand(this.onStandStill, "stand_still", "uimR2EDMenuStandInPlace", "r2_toolbar_stand_still.tga", false))
120 else
122 if activityWnd then
123 table.insert(dest, "Rest In Zone")
124 table.insert(dest, "Hunt In Zone")
125 else
126 table.insert(dest, this:buildActivityCommand(this.onPickRestZone, "rest_zone", "uimR2EDMenuPickRestZone", "r2ed_toolbar_rest_zone.tga", true))
127 table.insert(dest, this:buildActivityCommand(this.onPickHuntZone, "hunt_zone", "uimR2EDMenuPickHuntZone", "r2ed_toolbar_hunt_zone.tga", false))
130 --table.insert(dest, this:buildActivityCommand(this.onPickGuardZone, "guard_zone", "uimR2EDMenuPickGuardZone", "r2ed_toolbar_guard_zone.tga", true))
131 elseif category == "WorkerKitin" then
133 if activityWnd then
134 table.insert(dest, "Feed In Zone")
135 table.insert(dest, "Follow Route")
136 table.insert(dest, "Patrol")
137 table.insert(dest, "Repeat Road")
138 table.insert(dest, "Stand Still")
139 --table.insert(dest, "Guard Zone")
140 else
141 table.insert(dest, this:buildActivityCommand(this.onPickFeedZone, "feed_zone", "uimR2EDMenuPickWorkZone", "r2ed_toolbar_work_zone.tga", true))
142 table.insert(dest, this:buildActivityCommand(this.onPickFollowRoute, "follow_route", "uimR2EDMenuFollowRoute", "r2_toolbar_follow_road.tga", false))
143 table.insert(dest, this:buildActivityCommand(this.onPickPatrolRoute, "patrol_route", "uimR2EDMenuPatrolRoute", "r2_toolbar_patrol_road.tga", false))
144 table.insert(dest, this:buildActivityCommand(this.onPickRepeatRoute, "repeat_route", "uimR2EDMenuRepeatRoute", "r2_toolbar_repeat_road.tga", false))
145 table.insert(dest, this:buildActivityCommand(this.onStandStill, "stand_still", "uimR2EDMenuStandInPlace", "r2_toolbar_stand_still.tga", false))
146 --table.insert(dest, this:buildActivityCommand(this.onPickGuardZone, "guard_zone", "uimR2EDMenuPickGuardZone", "r2ed_toolbar_guard_zone.tga", true))
148 elseif category == "SoldierKitin" then
149 if activityWnd then
150 table.insert(dest, "Guard Zone")
151 table.insert(dest, "Follow Route")
152 table.insert(dest, "Patrol")
153 table.insert(dest, "Repeat Road")
154 table.insert(dest, "Stand Still")
155 else
156 table.insert(dest, this:buildActivityCommand(this.onPickGuardZone, "guard_zone", "uimR2EDMenuPickGuardZone", "r2ed_toolbar_guard_zone.tga", true))
157 table.insert(dest, this:buildActivityCommand(this.onPickFollowRoute, "follow_route", "uimR2EDMenuFollowRoute", "r2_toolbar_follow_road.tga", false))
158 table.insert(dest, this:buildActivityCommand(this.onPickPatrolRoute, "patrol_route", "uimR2EDMenuPatrolRoute", "r2_toolbar_patrol_road.tga", false))
159 table.insert(dest, this:buildActivityCommand(this.onPickRepeatRoute, "repeat_route", "uimR2EDMenuRepeatRoute", "r2_toolbar_repeat_road.tga", false))
160 table.insert(dest, this:buildActivityCommand(this.onStandStill, "stand_still", "uimR2EDMenuStandInPlace", "r2_toolbar_stand_still.tga", false))
162 elseif not this:isBotObject() and not this:isPlant() then
163 -- activity (only if not a plant)
164 this:addPrimitiveActivities(dest, activityWnd)
165 end
166 end,
168 -- for activities UI
169 getAvailableActivities = function(this, dest)
170 r2.Classes.ActiveLogicEntity.getAvailableCommands(this, dest, true)
171 end,
172 --------------------------------------------------------------------------------------------
173 -- Called when the menu is displayed
174 onSetupMenu = function(this)
176 --this:delegate():onSetupMenu()
177 r2.Classes.LogicEntity.onSetupMenu(this)
178 local class = r2:getClass(this)
179 local isBO = this:isBotObject()
180 local isPlant = this:isPlant()
181 getUI(class.Menu .. ":activities").active = not isBO and not isPlant
183 if not isBO and not isPlant then
184 getUI(class.Menu .. ":activities").uc_hardtext = i18n.get("uimR2EDNewActivity")
186 end,
187 --------------------------------------------------------------------------------------------
188 -- function to change activity
189 onStandStill = function(this)
190 r2:setNPCStandInPlace(this)
191 end,
192 onPickWanderZone = function(this)
193 runAH(nil, "r2ed_picker_lua", "CursCanPickPos=curs_create.tga|CursCannotPickPos=curs_stop.tga|TestFunc=r2:testCanPickZoneForNPC|PickFunc=r2:affectZoneToSelectedNPC|PickPosFunc=r2:createZoneAndAffectZoneToNPC|WantMouseUp=true|IgnoreInstances=Npc,Road")
194 r2.ContextualCommands:highlightCommandButton("wander_zone")
195 end,
196 onPickRestZone = function(this)
197 runAH(nil, "r2ed_picker_lua", "CursCanPickPos=curs_create.tga|CursCannotPickPos=curs_stop.tga|TestFunc=r2:testCanPickZoneForNPC|PickFunc=r2:affectRestZoneToSelectedNPC|PickPosFunc=r2:createRestZoneAndAffectZoneToNPC|WantMouseUp=true|IgnoreInstances=Npc,Road")
198 r2.ContextualCommands:highlightCommandButton("rest_zone")
199 end,
200 onPickFeedZone = function(this)
201 runAH(nil, "r2ed_picker_lua", "CursCanPickPos=curs_create.tga|CursCannotPickPos=curs_stop.tga|TestFunc=r2:testCanPickZoneForNPC|PickFunc=r2:affectFeedZoneToSelectedNPC|PickPosFunc=r2:createFeedZoneAndAffectZoneToNPC|WantMouseUp=true|IgnoreInstances=Npc,Road")
202 r2.ContextualCommands:highlightCommandButton("feed_zone")
203 end,
204 onPickHuntZone = function(this)
205 runAH(nil, "r2ed_picker_lua", "CursCanPickPos=curs_create.tga|CursCannotPickPos=curs_stop.tga|TestFunc=r2:testCanPickZoneForNPC|PickFunc=r2:affectHuntZoneToSelectedNPC|PickPosFunc=r2:createHuntZoneAndAffectZoneToNPC|WantMouseUp=true|IgnoreInstances=Npc,Road")
206 r2.ContextualCommands:highlightCommandButton("hunt_zone")
207 end,
208 onPickGuardZone = function(this)
209 runAH(nil, "r2ed_picker_lua", "CursCanPickPos=curs_create.tga|CursCannotPickPos=curs_stop.tga|TestFunc=r2:testCanPickZoneForNPC|PickFunc=r2:affectGuardZoneToSelectedNPC|PickPosFunc=r2:createGuardZoneAndAffectZoneToNPC|WantMouseUp=true|IgnoreInstances=Npc,Road")
210 r2.ContextualCommands:highlightCommandButton("guard_zone")
211 end,
212 onPickFollowRoute = function(this)
213 runAH(nil, "r2ed_picker_lua", "CursCanPickPos=curs_create.tga|CursCannotPickPos=curs_stop.tga|TestFunc=r2:testCanPickRoadForNPC|PickFunc=r2:setBehaviorFollowRouteToNPC|PickPosFunc=r2:createRouteAndSetBehaviorFollowRouteToNPC|WantMouseUp=true|IgnoreInstances=Npc, Region ")
214 r2.ContextualCommands:highlightCommandButton("follow_route")
215 end,
216 onPickPatrolRoute = function(this)
217 runAH(nil, "r2ed_picker_lua", "CursCanPickPos=curs_create.tga|CursCannotPickPos=curs_stop.tga|TestFunc=r2:testCanPickRoadForNPC|PickFunc=r2:setBehaviorPatrolRouteToNPC|PickPosFunc=r2:createRouteAndSetBehaviorPatrolRouteToNPC|WantMouseUp=true|IgnoreInstances=Npc,Region")
218 r2.ContextualCommands:highlightCommandButton("patrol_route")
219 end,
220 onPickRepeatRoute = function(this)
221 runAH(nil, "r2ed_picker_lua", "CursCanPickPos=curs_create.tga|CursCannotPickPos=curs_stop.tga|TestFunc=r2:testCanPickRoadForNPC|PickFunc=r2:setBehaviorRepeatRoadToNPC|PickPosFunc=r2:createRoadAndSetBehaviorRepeatRoadToNPC|WantMouseUp=true|IgnoreInstances=Npc,Region")
222 r2.ContextualCommands:highlightCommandButton("repeat_route")
223 end,
224 ---------------------------------------------------------------------------------------------------------
225 -- From base class
226 isSequencable = function(this)
227 return not this:isPlant() and not this:isBotObject()
228 end,
230 ---------------------------------------------------------------------------------------------------------
231 -- From base class
232 getActivityVerbLookupName = function (this, activityName)
233 if this.Category == "WorkerKitin" and activityName == "Feed In Zone" then
234 return "Work In Zone"
236 return activityName
237 end,
238 initEventValuesMenu = function(this, menu, categoryEvent)
240 -- activity sequences
241 for ev=0,menu:getNumLine()-1 do
243 local eventType = tostring(menu:getLineId(ev))
245 if r2.events.eventTypeWithValue[eventType] == "Number" then
246 menu:addSubMenu(ev)
247 local subMenu = menu:getSubMenu(ev)
248 local func = ""
249 for i=0, 9 do
250 local uc_name = ucstring()
251 uc_name:fromUtf8( tostring(i) )
252 func = "r2.events:setEventValue('','" .. categoryEvent .."','".. tostring(i).."')"
253 subMenu:addLine(uc_name, "lua", func, tostring(i))
256 elseif r2.events.eventTypeWithValue[eventType]~=nil then
257 menu:addSubMenu(ev)
258 local subMenu = menu:getSubMenu(ev)
260 for s=0, this:getBehavior().Activities.Size-1 do
261 local sequence = this:getBehavior().Activities[s]
262 local func = ""
263 if r2.events.eventTypeWithValue[eventType]=="ActivitySequence" then
264 func = "r2.events:setEventValue('".. sequence.InstanceId .."','" .. categoryEvent .."')"
267 local uc_name = ucstring()
268 uc_name:fromUtf8(sequence:getName())
269 subMenu:addLine(uc_name, "lua", func, sequence.InstanceId)
272 if this:getBehavior().Activities.Size==0 then
273 subMenu:addLine(i18n.get("uiR2EdNoSelelection"), "", "", "")
275 -- activity steps
276 elseif r2.events.eventTypeWithValue[eventType]=="ActivityStep" then
278 for s=0,subMenu:getNumLine()-1 do
279 local sequenceId = tostring(subMenu:getLineId(s))
280 local sequence = r2:getInstanceFromId(sequenceId)
281 assert(sequence)
283 subMenu:addSubMenu(s)
284 local activitiesMenu = subMenu:getSubMenu(s)
286 for a=0, sequence.Components.Size-1 do
287 local activity = sequence.Components[a]
288 local uc_name = ucstring()
289 uc_name:fromUtf8(activity:getShortName())
290 activitiesMenu:addLine(uc_name, "lua",
291 "r2.events:setEventValue('".. activity.InstanceId .."','" .. categoryEvent .."')", activity.InstanceId)
294 -- no activity in the sequence
295 if sequence.Components.Size==0 then
296 activitiesMenu:addLine(i18n.get("uiR2EdNoSelelection"), "", "", "")
302 end,
305 Behavior = {
306 Name="Behavior",
307 BaseClass="LogicEntityBehavior",
308 Prop=
310 {Name="Type", Type="String",DefaultValue=""},--TEMP
311 {Name="ZoneId", Type="String"},--TEMP
312 {Name="Activities",Type="Table"},
313 {Name="ChatSequences",Type="Table"}
317 ------------------------------------------------------------------------------------------------------
318 Npc = {
319 PropertySheetHeader = r2.DisplayNpcHeader(),
320 Name="Npc",
321 InEventUI = true,
322 BaseClass="ActiveLogicEntity",
323 DisplayerVisual = "R2::CDisplayerVisualEntity",
324 DisplayerUI = "R2::CDisplayerLua",
325 DisplayerUIParams = "defaultUIDisplayer",
326 DisplayerProperties = "R2::CDisplayerLua",
327 DisplayerPropertiesParams = "npcPropertySheetDisplayer",
328 -----------------------------------------------------------------------------------------------
329 Parameters = {
331 ApplicableActions = {
332 "Activate",
333 "Deactivate", "Kill", "begin activity sequence",
334 "Sit Down", "Stand Up",
335 "Fight with player", "Fight with Npcs",
336 "Dont fight with player", "Dont fight with Npcs",
337 "Run", "Dont run",
338 -- "emits user event",
340 Events = {
341 "activation",
342 "desactivation", "death",
343 "end of activity step", "end of activity sequence",
344 "begin of activity step", "begin of activity sequence",
345 -- "user event emitted",
347 "targeted by player"
349 Conditions = {
350 --"is dead", "is alive", "is active", "is inactive",
351 "is dead", "is alive",
352 "is in activity sequence",
353 "is in activity step",
355 TextContexts = {
356 "NPC is dead", "NPC is alive"
358 TextParameters = {
360 LiveParameters = {
361 "is active", "current activity sequence and activity step",
362 "current chat sequence and chat step"
364 -----------------------------------------------------------------------------------------------
365 Prop=
367 {Name="Base", Type="String", WidgetStyle="StaticText", Category="Advanced", Visible=false},
368 {Name="Name", Type="String", DefaultInBase=1, MaxNumChar="32"},
369 {Name="Angle", Type="Number",
370 WidgetStyle="Slider", Min="0", Max="360",
371 --------------------
372 convertToWidgetValue =
373 function(value)
374 local result = math.fmod(math.floor(180 * value / math.pi), 360)
375 if result < 0 then result = 360 + result end
376 return result
377 end,
378 --------------------
379 convertFromWidgetValue =
380 function(value)
381 return math.pi * math.min(359, value) / 180
382 end,
384 { Name="PlayerAttackable", Type="Number", WidgetStyle="Boolean", Default="0", DefaultInBase=1,
385 Visible=function(this) return this:isGroupedAndLeader() or not this:isGrouped() and not this:isBotObject() and this:canUpdatePlayerAttackable() end
388 Name="BotAttackable", Type="Number", WidgetStyle="Boolean", Default="0", DefaultInBase=1,
389 Visible=function(this) return this:isGroupedAndLeader() or not this:isGrouped() and not this:isBotObject() and this:canUpdateBotAttackable() end
391 -- {
392 -- Name="UseFame", Type="Number", WidgetStyle="Boolean", Default="0", DefaultInBase=1,
393 -- Visible=function(this) return this.SubCategory and ( this.SubCategory == "Kami" or this.SubCategory == "Karavan") end
394 -- },
397 Name="AutoSpawn", Type="Number", WidgetStyle="Boolean", Default="0", DefaultInBase=1,
398 --Visible=function(this) return not this:isBotObject() end
399 Visible = function(this) return this:isGroupedAndLeader() or not this:isGrouped() and not this:isBotObject() end
402 Name="NoRespawn", Type="Number", WidgetStyle="Boolean", Default="0", DefaultInBase=1,
403 Visible=function(this) return this:isGroupedAndLeader() or not this:isGrouped() and not this:isBotObject() end
405 {Name="Aggro", Type="Number", Min="0", Max="120", DefaultValue="30", DefaultInBase=1,
406 Visible=function(this) return this:isGroupedAndLeader() or not this:isGrouped() and not this:isBotObject() end
408 {Name="TypeNPC", Type="Number", WidgetStyle="EnumDropDown", SecondRequestFunc=r2.updateType,
409 Enum= {}, Visible=true, DefaultValue="-1",
414 --{Name="TestRefId", Type="RefId", Category="uiR2EDRollout_Test"},
420 isGroupedAndLeader = function(this)
421 if this:isGrouped() and this:isLeader() then return true end
422 return false
423 end,
425 TreeIcon= function(this)
427 if this:isKindOf("NpcCreature") or this:isKindOf("NpcPlant") then
428 return "r2ed_icon_creatures.tga"
429 elseif not this:isBotObject() then
430 return "r2ed_icon_npc.tga"
433 return ""
434 end,
436 PermanentTreeIcon= function(this)
437 if this:isKindOf("NpcCreature") or this:isKindOf("NpcPlant") then
438 return "r2ed_icon_permanent_creatures.tga"
439 elseif not this:isBotObject() then
440 return "r2ed_permanent_node.tga"
443 return ""
444 end,
446 ---------------------------------------------------------------------------------------------------------
447 -- get select bar type
448 SelectBarType = function(this)
449 if not this:isBotObject() then
450 return i18n.get("uiR2EDScene"):toUtf8()
451 else
452 return i18n.get("uiR2EDbotObjects"):toUtf8()
454 end,
456 ---------------------------------------------------------------------------------------------------------
457 -- from base class
458 getContextualTreeIcon = function(this)
459 if this:getParentAct():isBaseAct() then
460 return this:getPermanentTreeIcon()
462 return ""
463 end,
465 getSelectBarIcon = function(this)
466 if this:isBotObject() then
467 return "r2ed_icon_botobject.tga"
468 else
469 return r2.Classes.BaseClass.getContextualTreeIcon(this)
471 end,
473 ----------------------------------------------
474 updatePermanentStatutIcon = function(this)
475 --this.DisplayerVisual:updatePermanentStatutIcon(this:getContextualTreeIcon())
476 this.DisplayerVisual:updatePermanentStatutIcon(this:getPermanentStatutIcon())
477 end,
479 --------------------------------------------------------------------------------------------
480 onPostCreate= function(this)
481 if this.BoxSelection == 1 and this.DisplayerVisual ~= nil then -- read in palette
482 this.DisplayerVisual.SelectionDisplayMode = 1
484 if this:isBotObject() then
485 this.DisplayerVisual.DisplayMode = select(r2.BotObjectsFrozen, 2, 0)
487 end,
488 onActChanged = function(this)
489 if this:isBotObject() then
490 this.DisplayerVisual.DisplayMode = select(r2.BotObjectsFrozen, 2, 0)
492 end,
493 --------------------------------------------------------------------------------------------
494 -- from WorldObject
495 isDisplayModeToggleSupported = function(this, displayMode)
496 if not this:isBotObject() then
497 return displayMode == 3
498 end
499 return false
500 end,
501 --------------------------------------------------------------------------------------------
502 -- Test if this entity is a bot object
503 isBotObject = function(this)
504 return r2:isBotObject(this.SheetClient)
505 end,
508 canUpdatePlayerAttackable = function(this)
509 if this.CanUpdatePlayerAttackable == 0 then return false end
510 if this.CanUpdatePlayerAttackable == 1 then return true end
511 return this:isBotObject() == false
512 end,
514 canUpdateBotAttackable = function(this)
515 return this:isBotObject() == false
516 end,
518 --------------------------------------------------------------------------------------------
519 -- Test if this entity is a plant
520 isPlant = function(this)
521 return string.match(this.SheetClient, "cp[%w_]*%.creature")
522 end,
523 --------------------------------------------------------------------------------------------
524 -- check if that npc is the leader of its group
525 isLeader = function(this)
526 if not this:isGrouped() then
527 return false
528 end
529 return this.IndexInParent == 0
530 end,
531 --------------------------------------------------------------------------------------------
532 -- return the group of this npc if it has one, else return nil
533 getParentGroup = function(this)
534 if this.ParentInstance:isKindOf("NpcGrpFeature")
535 then
536 return this.ParentInstance
537 else
538 return nil
540 end,
541 --------------------------------------------------------------------------------------------
542 -- change the mouse to choose a new group to group with
543 onChooseGroup = function(this)
544 if this:isGrouped() then return end
545 runAH(nil, "r2ed_picker_lua", "TestFunc=r2:testCanGroupSelectedInstance|PickFunc=r2:groupSelectedInstance")
546 r2.ContextualCommands:highlightCommandButton("group")
547 end,
548 --------------------------------------------------------------------------------------------
549 -- if this npc was part of a group, ungroup it
550 onUngroup = function(this)
551 r2:ungroup(this)
552 end,
553 --------------------------------------------------------------------------------------------
554 -- If this npc is part of a group, make it the leader of its group
555 onSetAsLeader = function(this)
556 if this:isLeader() then return end
557 r2:setAsGroupLeader(this)
558 end,
559 --------------------------------------------------------------------------------------------
560 -- from 'BaseClass'
561 getAvailableCommands = function(this, dest)
562 --local result = this:delegate():getAvailableCommands(this)
563 r2.Classes.ActiveLogicEntity.getAvailableCommands(this, dest)
565 if not this:isBotObject() and not this:isPlant() then
566 if not this:isGrouped() then
567 table.insert(dest, this:buildCommand(this.onChooseGroup, "group", "uimR2EDMenuGroup", "r2_toolbar_group.tga", true))
568 else
569 table.insert(dest, this:buildCommand(this.onUngroup, "ungroup", "uimR2EDMenuUngroup", "r2_toolbar_ungroup.tga", true))
570 if not this:isLeader() then
571 table.insert(dest, this:buildCommand(this.onSetAsLeader, "set_as_leader", "uimR2EDMenuSetAsGroupLeader", "r2_toolbar_set_as_leader.tga", false))
574 --debugInfo(this.SheetClient)
575 end
577 this:getAvailableDisplayModeCommands(dest)
578 end,
579 --------------------------------------------------------------------------------------------
580 -- from 'BaseClass'
581 getParentTreeNode = function(this)
582 if not this:isInDefaultFeature() then
583 return r2.Classes.ActiveLogicEntity.getParentTreeNode(this)
585 if this:isBotObject() then
586 local container = getUI("ui:interface:r2ed_scenario")
587 --return {container:find("content_tree_list"):getRootNode():getNodeFromId("scenery_objects")}
588 return {container:find("content_tree_list"):getRootNode()}
589 elseif ( this:isKindOf("NpcCreature") or this:isKindOf("NpcPlant") ) then
590 return this:getParentAct():getContentTreeNodes("creatures")
591 else
592 return this:getParentAct():getContentTreeNodes("people")
593 end
594 end,
595 --------------------------------------------------------------------------------------------
596 -- special handler for deletion : this method is called when the user click on 'delete' in the
597 -- context menu and should perform the actual deletion
598 onDelete = function(this)
599 if this.User.DeleteInProgress == true then return end
600 this.User.DeleteInProgress = true
601 this:setDeleteActionName()
602 -- if deleted object is not in the default group, and was the last of its group, then
603 -- its parent group should be removed
604 if not this:isInDefaultFeature() then
605 if this.Parent.Size <= 2 then
606 local parentTable = this.Parent
607 local parentGroup = this.ParentInstance
608 local defaultFeature = this:getParentAct():getDefaultFeature()
609 for i = parentTable.Size - 1, 0, -1 do
610 if parentTable[i].InstanceId ~= this.InstanceId then
611 parentTable[i]:requestMakePosRelativeTo(defaultFeature)
612 r2:setSelectedInstanceId(parentTable[i].InstanceId)
613 r2.requestMoveNode(parentTable[i].InstanceId, "", -1, defaultFeature.InstanceId, "Components", -1)
614 break
616 end
617 r2.requestEraseNode(parentGroup.InstanceId, "", -1)
618 r2.requestEndAction()
619 return
621 end
622 this:selectNext()
623 r2.requestEraseNode(this.InstanceId, "", -1)
624 r2.requestEndAction()
625 end,
626 --------------------------------------------------------------------------------------------
627 -- return the behavior object, depending on wether this npc is grouped or not
628 getBehavior = function(this)
629 if this:isGrouped() and this.ParentInstance:isKindOf("NpcGrpFeature") then
630 return this.ParentInstance.Components[0].Behavior
631 else
632 return this.Behavior
634 end,
635 -----------------------------------------------------------------------------------------------
636 -- from base class
637 hasScenarioCost = function(this)
638 return true
639 end,
640 -----------------------------------------------------------------------------------------------
641 -- from base class
642 isCopyable = function(this)
643 return true
644 end,
645 -----------------------------------------------------------------------------------------------
646 -- from base class
647 paste = function(src, newPlace, srcInstanceId)
649 local Q, leftQ, leftStaticQ = r2:getLeftQuota()
650 local quota = leftQ
651 if r2:isBotObject(r2.getPropertyValue(src, "SheetClient")) then quota = leftStaticQ end
652 if quota <= 0 then
653 r2:makeRoomMsg()
654 return
656 local options =
658 CopyEvents = 0,
659 CopyActivities = 0,
660 -- CopyChatSequences = 0
661 DuplicateGroup = -1
664 -- if component is the leader and original group is still present, then give the option to duplicate the whole group
665 local srcInstance
666 if srcInstanceId then
667 srcInstance = r2:getInstanceFromId(srcInstanceId)
669 local groupCopy = nil
670 if srcInstance and srcInstance:isLeader() then
671 groupCopy = srcInstance.ParentInstance:copy()
672 groupCopy = r2.Classes[groupCopy.Class].newCopy(groupCopy)
673 options.DuplicateGroup = 0 -- offer option to do the copy
675 if srcInstance and srcInstance.isBotObject then
676 if srcInstance:isBotObject() then
677 if not r2:checkStaticQuota() then return end
678 else
679 if not r2:checkAiQuota() then return end
684 local function paramsOk(options)
685 if options.DuplicateGroup == 1 then
686 r2.Classes[groupCopy.Class].paste(groupCopy, src.Position, nil, options)
687 return
689 if options.CopyActivities == 0 then
690 src.ActivitiesId = {}
691 src.Behavior.Activities = {}
693 if options.CopyEvents == 0 then
694 src.Behavior.Actions = {}
696 --if options.CopyChatSequences == 0 then
697 -- src.Behavior.ChatSequences = {}
698 -- end
699 if newPlace then
700 src.Position.x, src.Position.y, src.Position.z = r2:getPastePosition()
701 end
702 r2:setCookie(src.InstanceId, "Select", true)
703 if r2:isBotObject(r2.getPropertyValue(src, "SheetClient")) then -- not already an object, so can't call a method yet ...
704 -- add to permanent content
705 r2.requestInsertNode(r2.Scenario:getBaseAct():getDefaultFeature().InstanceId , "Components",-1,"", src)
706 else
707 -- insert in current act
708 r2.requestInsertNode(r2:getCurrentAct():getDefaultFeature().InstanceId , "Components", -1,"", src)
711 local function paramsCancel()
712 debugInfo('paste was cancelled')
714 if table.getn(src.Behavior.Activities) == 0 then
715 options.CopyActivities = -1
717 if table.getn(src.Behavior.Actions) == 0 then
718 options.CopyEvents = -1
719 end
720 --if table.getn(src.Behavior.ChatSequences) == 0 then
721 -- options.CopyChatSequences = -1
722 -- end
723 if options.CopyActivities >= 0 or
724 options.CopyEvents >= 0
725 --or options.CopyChatSequences >= 0
726 then
727 r2:doForm("SpecialPaste", options, paramsOk, paramsCancel)
728 else
729 -- nothing specific to copy, do direct paste
730 paramsOk(options)
732 end,
733 -----------------------------------------------------------------------------------------------
734 -- from base class
735 pasteGhost = function(src)
737 local target
738 if r2:isBotObject(r2.getPropertyValue(src, "SheetClient")) then -- not already an object, so can't call a method yet ...
739 -- insert in current act
740 target = r2.Scenario:getBaseAct():getDefaultFeature()
741 if not r2:checkStaticQuota() then return end
742 else
743 -- insert in current act
744 target = r2:getCurrentAct():getDefaultFeature()
745 if not r2:checkAiQuota() then return end
747 -- create the 'Ghosts' entry locally if it doesn't already exists
748 if target.Ghosts == nil then
749 r2.requestInsertGhostNode(target.InstanceId, "", -1, "Ghosts", {})
750 end
752 r2.requestInsertGhostNode(target.InstanceId, "Ghosts",-1,"", src)
753 -- insertion should have been done right now
754 return r2:getInstanceFromId(src.InstanceId)
755 end,
757 getAiCost = function(this)
758 if this.User.GhostDuplicate then return 0 end
759 assert(this)
760 if this.IsBotObject == 0 then
761 return 1
763 return 0
764 end,
766 getStaticObjectCost = function(this)
767 if this.User.GhostDuplicate then return 0 end
768 assert(this)
769 if this.IsBotObject == 1 then
770 return 1
772 return 0
773 end,
775 -- from 'ActiveLogicEntity'
776 getApplicableActions = function(this)
777 local actions = r2.Classes[this.Class].ApplicableActions
779 if not this:canUpdateBotAttackable() then
780 local actionsTemp = {}
781 for k, v in pairs(actions) do
782 if v~="Fight with Npcs" and v~="Dont fight with Npcs" then --and v~="Sit Down" and v~="Stand Up" then
783 table.insert(actionsTemp, v)
786 actions = actionsTemp
789 if not this:canUpdatePlayerAttackable() then
790 local actionsTemp = {}
791 for k, v in pairs(actions) do
792 if v~="Fight with player" and v~="Dont fight with player" then -- and v~="Sit Down" and v~="Stand Up" then
793 table.insert(actionsTemp, v)
796 actions = actionsTemp
799 return actions
800 end,
803 ------------------------------------------------------------------------------------------------------
804 -- a 'custom' npc : this is a npc that is customizable
805 NpcCustom = {
806 Name="NpcCustom",
807 BaseClass="Npc",
808 DisplayerProperties = "R2::CDisplayerLua",
809 DisplayerPropertiesParams = "npcCustomPropertySheetDisplayer",
810 Prop=
812 -- Look (all widgets have Visible=false because they are edited in the npc editor, not in the property sheet)
814 { Name="GabaritHeight", Type="Number", Visible=false, DefaultInBase=1 },
815 { Name="GabaritTorsoWidth", Type="Number", Visible=false, DefaultInBase=1 },
816 { Name="GabaritArmsWidth", Type="Number", Visible=false, DefaultInBase=1 },
817 { Name="GabaritLegsWidth", Type="Number", Visible=false, DefaultInBase=1 },
818 { Name="GabaritBreastSize", Type="Number", Visible=false, DefaultInBase=1 },
820 { Name="HairType", Type="Number", Visible=false, DefaultInBase=1 },
821 { Name="HairColor", Type="Number", Visible=false, DefaultInBase=1 },
822 { Name="Tattoo", Type="Number", Visible=false, DefaultInBase=1 },
823 { Name="EyesColor", Type="Number", Visible=false, DefaultInBase=1 },
825 { Name="MorphTarget1", Type="Number", Visible=false, DefaultInBase=1 },
826 { Name="MorphTarget2", Type="Number", Visible=false, DefaultInBase=1 },
827 { Name="MorphTarget3", Type="Number", Visible=false, DefaultInBase=1 },
828 { Name="MorphTarget4", Type="Number", Visible=false, DefaultInBase=1 },
829 { Name="MorphTarget5", Type="Number", Visible=false, DefaultInBase=1 },
830 { Name="MorphTarget6", Type="Number", Visible=false, DefaultInBase=1 },
831 { Name="MorphTarget7", Type="Number", Visible=false, DefaultInBase=1 },
832 { Name="MorphTarget8", Type="Number", Visible=false, DefaultInBase=1 },
834 --{ Name="Sex", Type="Number", Visible=false, DefaultInBase=1 },
836 { Name="JacketModel", Type="Number", Visible=false, DefaultInBase=1 },
837 { Name="TrouserModel", Type="Number", Visible=false, DefaultInBase=1 },
838 { Name="FeetModel", Type="Number", Visible=false, DefaultInBase=1 },
839 { Name="HandsModel", Type="Number", Visible=false, DefaultInBase=1 },
840 { Name="ArmModel", Type="Number", Visible=false, DefaultInBase=1 },
841 { Name="WeaponRightHand", Type="Number", Visible=false, DefaultInBase=1 },
842 { Name="WeaponLeftHand", Type="Number", Visible=false, DefaultInBase=1 },
844 { Name="JacketColor", Type="Number", Visible=false, DefaultInBase=1 },
845 { Name="ArmColor", Type="Number", Visible=false, DefaultInBase=1 },
846 { Name="HandsColor", Type="Number", Visible=false, DefaultInBase=1 },
847 { Name="TrouserColor", Type="Number", Visible=false, DefaultInBase=1 },
848 { Name="FeetColor", Type="Number", Visible=false, DefaultInBase=1 },
850 { Name="LinkColor", Type="Number", Visible=false, DefaultInBase=0 },
852 --{ Name="Notes", Type="String", Visible=false, DefaultInBase=1 },
853 { Name="Function", Type="String", Visible=false, DefaultInBase=1 },
854 --{ Name="Level", Type="String", Visible=false, DefaultInBase=1 },
855 { Name="Profile", Type="String", Visible=false, DefaultInBase=1 },
856 {Name="Speed", Type="Number", WidgetStyle="EnumDropDown", Category="uiR2EDRollout_NpcCustom",
857 Enum= { "uiR2EDWalk", "uiR2EDRun"},
858 Visible=true
860 {Name="Level", Type="Number", WidgetStyle="EnumDropDown", Category="uiR2EDRollout_NpcCustom",
861 Enum= { "uiR2EDLowLevel", "uiR2EDAverageLevel", "uiR2EDHighLevel", "uiR2EDVeryHighLevel"}, SecondRequestFunc=r2.updateLevel,
862 Visible=function(this) return this:isGroupedAndLeader() or not this:isGrouped() and not this:isBotObject() end
865 -- from "BaseClass"
866 getAvailableCommands = function(this, dest)
867 --local result = this:delegate():getAvailableCommands()
868 r2.Classes.Npc.getAvailableCommands(this, dest)
869 end,
870 -- Additionnal property sheet header to access npc customisation
871 PropertySheetHeader =
873 <ctrl style="text_button_16" id="customize" active="true" posref="TL TL" onclick_l="lua" x="0" y="0" params_l="r2:getSelectedInstance():customizeLook()" hardtext="uiR2EDCustomizeLook"/>
875 -- Pop the npc editor
876 customizeLook = function(this)
877 -- if the npc edition window is not shown, display it
878 local npcEditionWnd = getUI("ui:interface:r2ed_npc")
879 if not npcEditionWnd.active then
880 npcEditionWnd.active = true
881 npcEditionWnd:updateCoords()
882 npcEditionWnd:center()
883 -- update the npc window content
884 this.DisplayerProperties:updateAll(this)
885 else
886 setTopWindow(npcEditionWnd)
887 npcEditionWnd:blink(1)
889 end,
890 -----------------------------------------------------------------------------------------------
891 -- from base class
892 hasScenarioCost = function(this)
893 return true
894 end,
895 -----------------------------------------------------------------------------------------------
896 -- special paste with renaming
897 paste = function(src, newPlace, srcInstanceId)
898 local base = r2.getPaletteElement(src.Base)
899 local sex = r2.getPropertyValue(base, "Sex")
901 r2.Classes.Npc.paste(src, newPlace, srcInstanceId)
902 end,
905 ------------------------------------------------------------------------------------------------------
906 -- NPC CREATURE
907 NpcCreature = {
908 Name="NpcCreature",
909 InEventUI = true,
910 BaseClass="Npc",
911 DisplayerProperties = "R2::CDisplayerLua",
912 DisplayerPropertiesParams = "npcPropertySheetDisplayer",
913 Prop=
915 {Name="Speed", Type="Number", WidgetStyle="EnumDropDown", Category="uiR2EDRollout_Default",
916 Enum= { "uiR2EDWalk", "uiR2EDRun"},
917 Visible=function(this) return not this:isKindOf("NpcPlant") end,
921 getApplicableActions = function(this)
922 local actions = r2.Classes[this.Class].ApplicableActions
924 local actionsTemp = {}
925 for k, v in pairs(actions) do
926 if v~="Sit Down" and v~="Stand Up" then
927 table.insert(actionsTemp, v)
929 end
931 return actionsTemp
932 end,
935 ------------------------------------------------------------------------------------------------------
936 -- NPC PLANT
937 NpcPlant = {
938 Name="NpcPlant",
939 InEventUI = true,
940 BaseClass="NpcCreature",
941 DisplayerProperties = "R2::CDisplayerLua",
942 DisplayerPropertiesParams = "npcPropertySheetDisplayer",
943 Prop=
948 ApplicableActions = {
949 "Activate",
950 "Deactivate", "Kill",
952 Events = {
953 "activation",
954 "desactivation", "death",
956 Conditions = {},
961 -- base class for primitives, include copy-paste code
963 BaseClass="WorldObject",
964 Name="BasePrimitive",
965 Prop=
967 {Name="Name", Type="String", MaxNumChar="32"}
969 --------------------------------------------------------------------------------------------
970 onPostCreate = function(this)
971 this.DisplayerVisual.DisplayMode = r2:getPrimDisplayMode()
972 this.DisplayerVisual.ContextualVisibilityActive = r2.PrimDisplayContextualVisibility
973 end,
974 onActChanged = function(this)
975 this.DisplayerVisual.ContextualVisibilityActive = r2.PrimDisplayContextualVisibility
976 end,
977 --------------------------------------------------------------------------------------------
978 onPostCreate = function(this)
979 this.DisplayerVisual.DisplayMode = r2:getPrimDisplayMode()
980 this.DisplayerVisual.ContextualVisibilityActive = r2.PrimDisplayContextualVisibility
981 end,
982 onActChanged = function(this)
983 this.DisplayerVisual.ContextualVisibilityActive = r2.PrimDisplayContextualVisibility
984 end,
985 --------------------------------------------------------------------------------------------
986 -- from WorldObject
987 canChangeDisplayMode = function(this)
988 return true
989 end,
990 -----------------------------------------------------------------------------------------------
991 -- from base class
992 isCopyable = function(this)
993 return true
994 end,
995 isNextSelectable = function(this)
996 return true
997 end,
998 -----------------------------------------------------------------------------------------------
999 -- from base class
1000 getAvailableCommands = function(this, dest)
1001 r2.Classes.WorldObject.getAvailableCommands(this, dest) -- fill by ancestor
1002 table.insert(dest, this:buildCommand(this.onNewVertexTool, "new_vertex", "uimR2EDAddNewVertices", "r2ed_tool_new_vertex.tga"))
1003 end,
1004 -----------------------------------------------------------------------------------------------
1005 onNewVertexTool = function(this)
1006 r2:setCurrentTool('R2::CToolNewVertex')
1007 r2.ContextualCommands:highlightCurrentCommandButton("new_vertex")
1008 end,
1009 -----------------------------------------------------------------------------------------------
1010 -- from base class
1011 paste = function(src, newPlace, srcInstanceId)
1012 --if r2:getLeftQuota() <= 0 then
1013 -- r2:makeRoomMsg()
1014 -- return
1015 --end
1016 if newPlace then
1017 --if r2.Classes[src.Class].isCopyInsideCurrIsland(src) then
1018 -- src.Position.x = src.Position.x + 4 * (math.random() - 0.5)
1019 -- src.Position.y = src.Position.y + 4 * (math.random() - 0.5)
1020 -- src.Position.z = src.Position.z + 4 * (math.random() - 0.5)
1021 --else
1022 local mx, my, mz = r2.Classes[src.Class].getCopyCenter(src)
1023 -- express in world
1024 mx = mx + src.Position.x
1025 my = my + src.Position.y
1026 mz = mz + src.Position.z
1027 -- get player pos in world
1028 local px, py, pz = getPlayerPos()
1030 -- add delta to have primitive center in world over player pos
1031 src.Position.x = src.Position.x + px - mx + 4 * (math.random() - 0.5)
1032 src.Position.y = src.Position.y + py - my + 4 * (math.random() - 0.5)
1033 src.Position.z = src.Position.z + pz - mz + 4 * (math.random() - 0.5)
1034 --end
1035 end
1036 r2.requestInsertNode(r2.Scenario:getBaseAct():getDefaultFeature().InstanceId, "Components", -1, "", src)
1037 r2:setCookie(src.InstanceId, "Select", true)
1038 end,
1039 -----------------------------------------------------------------------------------------------
1040 -- Function (not method) : test if the passed primitive copy (obtained
1041 -- with BasePrimitive:copy is inside the current island
1042 -- The default behavior is to test each vertices inside the 'Points' array
1043 -- are inside the current island rectangle. If a derivers is not defined
1044 -- as a set of points, it should provide the good test here
1045 isCopyInsideCurrIsland = function(src)
1046 for k, v in pairs(src.Points) do
1047 if not r2:isInIslandRect(v.Position.x, v.Position.y) then return false end
1049 return true
1050 end,
1051 -----------------------------------------------------------------------------------------------
1052 -- Function (not method) : return the center a a copîed primitive obtained with
1053 -- BasePrimitive:copy
1054 getCopyCenter = function(src)
1055 local x = 0
1056 local y = 0
1057 local z = 0
1058 local count = 0
1059 for k, v in pairs(src.Points) do
1060 x = x + v.Position.x
1061 y = y + v.Position.y
1062 z = z + v.Position.z
1063 count = count + 1
1065 if count ~= 0 then
1066 x = x / count
1067 y = y / count
1068 z = z / count
1070 return x, y, z
1071 end,
1072 -----------------------------------------------------------------------------------------------
1073 -- from base class
1074 pasteGhost = function(src)
1075 --if r2:getLeftQuota() <= 0 then
1076 -- r2:makeRoomMsg()
1077 -- return
1078 --end
1079 target = r2.Scenario:getBaseAct():getDefaultFeature()
1080 if target.Ghosts == nil then
1081 r2.requestInsertGhostNode(target.InstanceId, "", -1, "Ghosts", {})
1082 end
1083 r2.requestInsertNode(target.InstanceId, "Ghosts", -1, "", src)
1084 return r2:getInstanceFromId(src.InstanceId)
1085 end,
1087 ------------------------------------------------------------------------------------------------------
1089 BaseClass="BasePrimitive",
1090 Name="Region",
1091 Menu="ui:interface:r2ed_base_menu",
1092 TreeIcon= function(this)
1093 if this:isInDefaultFeature() then return "" else return "r2ed_icon_region.tga" end
1094 end,
1095 DisplayerUI = "R2::CDisplayerLua",
1096 DisplayerUIParams = "defaultUIDisplayer",
1097 DisplayerVisual = "R2::CDisplayerVisualGroup",
1098 DisplayerVisualParams =
1100 Look = r2.PrimRender.RegionLook,
1101 InvalidLook = r2.PrimRender.RegionInvalidLook,
1103 ArrayName = "Points"
1105 Prop=
1107 -- {Name="Base", Type="String", WidgetStyle="StaticText", Category="Advanced"},
1108 {Name="Points", Type="Table"},
1110 --------------------------------------------------------------------------------------------
1111 getSelectBarIcon = function(this)
1112 return "r2ed_icon_region.tga"
1113 end,
1114 getAvailableCommands = function(this, dest)
1115 r2.Classes.BasePrimitive.getAvailableCommands(this, dest) -- fill by ancestor
1116 this:getAvailableDisplayModeCommands(dest)
1117 end,
1119 ---------------------------------------------------------------------------------------------------------
1120 -- get select bar type
1121 SelectBarType = function(this)
1122 return i18n.get("uiR2EDbotObjects"):toUtf8()
1123 end,
1124 --------------------------------------------------------------------------------------------
1125 -- from 'BaseClass'
1126 getParentTreeNode = function(this)
1127 -- if not this:isInDefaultFeature() then
1128 -- return r2.Classes.WorldObject.getParentTreeNode(this)
1129 -- end
1130 -- local tree = getUI("ui:interface:r2ed_scenario")
1131 -- return tree:find("content_tree_list"):getRootNode():getNodeFromId("places")
1133 return {}
1134 end,
1135 -----------------------------------------------------------------------------------------------
1136 -- from base class
1137 --getUsedQuota = function(this)
1138 -- return 1
1139 --end
1141 ------------------------------------------------------------------------------------------------------
1143 BaseClass="BasePrimitive",
1144 Name="Road",
1145 --DisplayerVisual = "R2::CDisplayerVisualRoad",
1146 DisplayerVisual = "R2::CDisplayerVisualGroup",
1147 TreeIcon= function(this)
1148 if this:isInDefaultFeature() then return "" else return "r2ed_icon_road.tga" end
1149 end,
1150 DisplayerVisualParams =
1152 Look = r2.PrimRender.RoadLook,
1153 InvalidLook = r2.PrimRender.RoadLookInvalid,
1155 ArrayName = "Points"
1157 DisplayerUI = "R2::CDisplayerLua",
1158 DisplayerUIParams = "defaultUIDisplayer",
1159 Menu="ui:interface:r2ed_base_menu",
1160 Prop=
1162 -- {Name="Base", Type="String", WidgetStyle="StaticText", Category="Advanced"},
1163 {Name="Points", Type="Table"}
1165 --------------------------------------------------------------------------------------------
1166 getSelectBarIcon = function(this)
1167 return "r2ed_icon_road.tga"
1168 end,
1170 ---------------------------------------------------------------------------------------------------------
1171 -- get select bar type
1172 SelectBarType = function(this)
1173 return i18n.get("uiR2EDbotObjects"):toUtf8()
1174 end,
1175 --------------------------------------------------------------------------------------------
1176 -- from 'BaseClass'
1177 getParentTreeNode = function(this)
1178 -- if not this:isInDefaultFeature() then
1179 -- return r2.Classes.WorldObject.getParentTreeNode(this)
1180 -- end
1181 -- local tree = getUI("ui:interface:r2ed_scenario")
1182 -- return tree:find("content_tree_list"):getRootNode():getNodeFromId("routes")
1184 return {}
1185 end,
1186 -----------------------------------------------------------------------------------------------
1187 -- from base class
1188 getAvailableCommands = function(this, dest)
1189 r2.Classes.BasePrimitive.getAvailableCommands(this, dest) -- fill by ancestor
1190 table.insert(dest, this:buildCommand(this.onExtendRoad, "extend_road", "uiR2EDExtendRoad", "r2ed_tool_extend_prim.tga"))
1191 this:getAvailableDisplayModeCommands(dest)
1192 end,
1193 -----------------------------------------------------------------------------------------------
1194 onExtendRoad = function(this)
1195 r2:setCurrentTool('R2::CToolDrawPrim',
1197 Look = r2.PrimRender.RoadCreateLook,
1198 InvalidLook = r2.PrimRender.RoadCreateInvalidLook,
1199 Type="Road",
1200 ExtendedPrimitiveId = this.InstanceId
1203 r2.ContextualCommands:highlightCurrentCommandButton("extend_road")
1204 end,
1205 -----------------------------------------------------------------------------------------------
1206 -- from base class
1207 --getUsedQuota = function(this)
1208 -- return 1
1209 --end
1211 ------------------------------------------------------------------------------------------------------
1213 BaseClass="WorldObject",
1214 Name="WayPoint",
1215 BuildPropertySheet = false,
1216 DisplayerVisual = "R2::CDisplayerVisualShape",
1217 DisplayerVisualParams = { ShapeName = r2.PrimRender.RoadCreateLook.VertexShapeName,
1218 Scale = r2.PrimRender.RoadCreateLook.VertexShapeScale,
1219 InheritDisplayMode = true
1221 DisplayerUI = "",
1222 Menu="ui:interface:r2ed_base_menu",
1223 Prop=
1225 -- NOTE : position inherit from 'WorldObject'
1227 onDelete = function(this)
1228 if this.User.DeleteInProgress == true then return end
1229 this.User.DeleteInProgress = true
1230 this:setDeleteActionName()
1231 -- if I'm the last in the array, then delete my parent
1232 if this.Parent.Size <= 2 then
1233 this.ParentInstance:selectNext()
1234 r2.requestEraseNode(this.ParentInstance.InstanceId, "", -1)
1235 else
1236 -- just delete my self
1237 this:selectNext()
1238 r2.requestEraseNode(this.InstanceId, "", -1)
1240 r2.requestEndAction()
1241 end,
1242 setDeleteActionName = function(this)
1243 r2.requestNewAction(i18n.get("uiR2EDDeletingWayPoint"))
1244 end,
1245 isNextSelectable = function(this)
1246 return true
1249 ------------------------------------------------------------------------------------------------------
1251 BaseClass="WorldObject",
1252 Name="RegionVertex",
1253 BuildPropertySheet = false,
1254 DisplayerVisual = "R2::CDisplayerVisualShape",
1255 DisplayerVisualParams = { ShapeName = r2.PrimRender.RegionCreateLook.VertexShapeName,
1256 Scale = r2.PrimRender.RegionCreateLook.VertexShapeScale,
1257 InheritDisplayMode = true
1259 DisplayerUI = "",
1260 Menu="ui:interface:r2ed_base_menu",
1261 Prop=
1263 -- NOTE : position inherit from 'WorldObject'
1265 setDeleteActionName = function(this)
1266 r2.requestNewAction(i18n.get("uiR2EDDeletingRegionVertex"))
1267 end,
1268 onDelete = function(this)
1269 if this.User.DeleteInProgress == true then return end
1270 this.User.DeleteInProgress = true
1271 this:setDeleteActionName()
1272 -- if I'm the last in the array, then delete my parent
1273 if this.Parent.Size <= 3 then
1274 this.ParentInstance:selectNext()
1275 r2.requestEraseNode(this.ParentInstance.InstanceId, "", -1)
1276 else
1277 -- just delete my self
1278 this:selectNext()
1279 r2.requestEraseNode(this.InstanceId, "", -1)
1281 r2.requestEndAction()
1282 end,
1283 isNextSelectable = function(this)
1284 return true
1287 ------------------------------------------------------------------------------------------------------
1289 BaseClass="BasePrimitive",
1290 Name="Place",
1291 DisplayerUI = "R2::CDisplayerLua",
1292 DisplayerUIParams = "defaultUIDisplayer",
1293 Menu="ui:interface:r2ed_base_menu",
1294 Prop=
1296 {Name="Radius", Type="Number"}
1298 -- from BasePrimitive
1299 isCopyInsideCurrIsland = function(src)
1300 return r2:isInIslandRect(src.Position.x, src.Position.y)
1301 end,
1302 -- from BasePrimitive
1303 getCopyCenter = function(src)
1304 return src.Position.x, src.Position.y, src.Position.z
1305 end,
1307 getAvailableCommands = function(this, dest)
1308 r2.Classes.BasePrimitive.getAvailableCommands(this, dest) -- fill by ancestor
1309 this:getAvailableDisplayModeCommands(dest)
1310 end,
1312 ------------------------------------------------------------------------------------------------------
1314 BaseClass="BaseClass",
1315 Name="Position",
1316 DisplayerUI = "",
1317 Prop=
1319 {Name="x", Type="Number"},
1320 {Name="y", Type="Number"},
1321 {Name="z", Type="Number"}
1323 -- test if this position is equal to another position (not necessarily an instance,
1324 -- may be any table with the { x = ..., y = ..., z = ... } format
1325 equals = function(this, other)
1326 return this.x == other.x and this.y == other.y and this.z == other.z
1327 end,
1328 -- return string version of position
1329 toString = function(this)
1330 return "(" .. tostring(this.x) .. ", " .. tostring(this.y) .. ", " .. tostring(this.z) .. ")"
1333 UserComponentHolder =
1335 BaseClass="LogicEntity",
1336 Name="UserComponentHolder",
1338 Menu="ui:interface:r2ed_feature_menu",
1339 DisplayerUI = "R2::CDisplayerLua",
1340 DisplayerUIParams = "defaultUIDisplayer",
1341 DisplayerVisual = "R2::CDisplayerVisualEntity",
1344 Parameters = {},
1346 ApplicableActions = {},
1348 Events = {},
1350 Conditions = {},
1352 TextContexts = {},
1354 TextParameters = {},
1356 LiveParameters = {},
1358 Prop =
1360 {Name="InstanceId", Type="String", WidgetStyle="StaticText", Visible = false},
1361 {Name="Name", Type="String"},
1362 {Name="Description", Type="String"},
1363 {Name="Components", Type="Table", Visible=false},
1366 getParentTreeNode = function(this)
1367 return this:getFeatureParentTreeNode()
1368 end,
1370 appendInstancesByType = function(this, destTable, kind)
1371 assert(type(kind) == "string")
1372 r2.Classes.LogicEntity.appendInstancesByType(this, destTable, kind)
1373 for k, component in specPairs(this.Components) do
1374 component:appendInstancesByType(destTable, kind)
1376 end,
1378 getSelectBarSons = function(this)
1379 return Components
1380 end,
1382 canHaveSelectBarSons = function(this)
1383 return false;
1384 end,
1386 onPostCreate = function(this)
1387 end,
1389 pretranslate = function(this, context)
1390 r2.Translator.createAiGroup(this, context)
1391 r2.Translator.pretranslateDefaultFeature(this, context)
1392 end,
1394 translate = function(this, context)
1395 r2.Translator.translateDefaultFeature(this, context, true)
1396 end,
1398 getActivitiesIds = r2.Translator.getDefaultFeatureActivitiesIds,
1399 -- TODO use sexy images
1400 getAvailableCommands = function(this, dest)
1401 r2.Classes.LogicEntity.getAvailableCommands(this, dest)
1402 table.insert(dest, this:buildActivityCommand(this.onPickAddEntity, "add_entity", "uimR2EDMenuPickAddEntity", "r2_toolbar_customize_look.tga", true))
1403 table.insert(dest, this:buildActivityCommand(this.onPickRemoveEntity, "remove_entity", "uimR2EDMenuPickRemoveEntity", "r2_toolbar_delete.tga", false))
1404 table.insert(dest, this:buildActivityCommand(this.onPickExport, "export", "uimR2EDMenuPickExport", "r2_toolbar_properties.tga", false))
1405 end,
1410 -- !feature.Components
1411 ------------------------------------------------------------------------------------------------------
1412 classLogicEntityBehaviorVersion = 1
1414 feature.Components.LogicEntityBehavior = {
1415 Name="LogicEntityBehavior",
1416 BaseClass="BaseClass",
1417 Version = classLogicEntityBehaviorVersion,
1418 Prop=
1420 {Name="Actions", Type="Table"},
1421 -- {Name="Reactions", Type="Table"}
1424 updateVersion = function(this, scenarioValue, currentValue)
1425 local patchValue = scenarioValue
1426 if patchValue < 1 then
1427 -- Patch only for old save (not the 0.0.3)
1428 if this.Reactions ~= nil then
1429 -- TODO use identifier instead
1430 r2.requestEraseNode(this.InstanceId, "Reactions", -1)
1431 end
1432 patchValue = 1
1435 if patchValue == currentValue then return true end
1436 return false
1441 ------------------------------------------------------------------------------------------------------
1442 local userComponentHolder = feature.Components.UserComponentHolder
1444 userComponentHolder.getLogicAction = function(entity, context, action)
1445 local firstAction, lastAction = nil,nil
1446 return firstAction, lastAction
1450 userComponentHolder.getLogicCondition = function(this, context, condition)
1451 return nil,nil
1455 userComponentHolder.getLogicEvent = function(this, context, event)
1456 local eventHandler, firstCondition, lastCondition = nil, nil, nil
1457 return eventHandler, firstCondition, lastCondition
1460 function userComponentHolder:registerMenu(logicEntityMenu)
1461 local name = i18n.get("uiR2EdUserComponent")
1462 logicEntityMenu:addLine(ucstring(name), "lua", "", "uiR2EdUserComponent")
1466 function userComponentHolder:getLogicTranslations()
1467 local logicTranslations = {
1468 ["ApplicableActions"] = {},
1469 ["Events"] = {},
1471 return logicTranslations
1473 function userComponentHolder.onPickExport(this)
1474 local refX = this.Position.x
1475 local refY = this.Position.y
1476 local refZ = this.Position.z
1478 local components = this.Components
1479 r2_core.UserComponentManager.CurrentDesc = this.Description
1480 local exportList = {}
1481 local k, v = next(components, nil)
1482 while k do
1483 if v.InstanceId then
1484 table.insert(exportList, v.InstanceId)
1486 k, v = next(components, k)
1488 r2_core.UserComponentManager:export(exportList, refX, refY, refZ)
1491 function userComponentHolder.create()
1492 if not r2:checkAiQuota() then return end
1494 local function paramsCancel()
1495 debugInfo("Cancel form for 'User Component' creation")
1497 local function posOk(x, y, z)
1498 debugInfo(string.format("Validate creation of 'User Component' at pos (%d, %d, %d)", x, y, z))
1499 if r2.mustDisplayInfo("UserComponent") == 1 then
1500 r2.displayFeatureHelp("UserComponent")
1502 local component = r2.newComponent("UserComponentHolder")
1503 component.Base = r2.Translator.getDebugBase("palette.entities.botobjects.user_event")
1504 component.Name = r2:genInstanceName(i18n.get("uiR2EdUserComponent")):toUtf8()
1506 component.Position.x = x
1507 component.Position.y = y
1508 component.Position.z = r2:snapZToGround(x, y)
1510 r2:setCookie(component.InstanceId, "DisplayProp", 1)
1511 r2.requestInsertNode(r2:getCurrentAct().InstanceId, "Features", -1, "", component)
1514 local function posCancel()
1515 debugInfo("Cancel choice 'User Component' position")
1516 end
1517 local creature = r2.Translator.getDebugCreature("object_component_user_event.creature")
1518 r2:choosePos(creature, posOk, posCancel, "createUserComponent")
1521 function userComponentHolder:registerMenu(logicEntityMenu)
1522 local name = i18n.get("uiR2EdUserComponent")
1523 logicEntityMenu:addLine(ucstring(name), "lua", "", "uiR2EdUserComponent")
1526 function userComponentHolder.onPickAddEntity(this)
1527 r2_core.CurrentHolderId = this.InstanceId
1528 runAH(nil, "r2ed_picker_lua", "CursCanPickPos=curs_create.tga|CursCannotPickPos=curs_stop.tga|TestFunc=r2_core:testIsExportable|PickFunc=r2_core:addEntityToExporter|PickPosFunc=r2_core:doNothing|WantMouseUp=true")
1529 r2.ContextualCommands:highlightCommandButton("add_entity")
1532 function userComponentHolder.onPickRemoveEntity(this)
1533 r2_core.CurrentHolderId = this.InstanceId
1534 runAH(nil, "r2ed_picker_lua", "CursCanPickPos=curs_create.tga|CursCannotPickPos=curs_stop.tga|TestFunc=r2_core:testCanPickUserComponentElement|PickFunc=r2_core:removeUserComponentElement|PickPosFunc=r2_core:doNothing|WantMouseUp=true")
1535 r2.ContextualCommands:highlightCommandButton("remove_entity")
1538 function userComponentHolder.onPostCreate(this)
1539 if this.User.DisplayProp and this.User.DisplayProp == 1 then
1540 r2:setSelectedInstanceId(this.InstanceId)
1541 r2:showProperties(this)
1542 this.User.DisplayProp = nil
1546 function userComponentHolder.onPickExport(this)
1547 local refX = this.Position.x
1548 local refY = this.Position.y
1549 local refZ = this.Position.z
1551 local components = this.Components
1552 r2_core.UserComponentManager.CurrentDesc = this.Description
1553 local exportList = {}
1554 local k, v = next(components, nil)
1555 while k do
1556 if v.InstanceId then
1557 table.insert(exportList, v.InstanceId)
1559 k, v = next(components, k)
1561 r2_core.UserComponentManager:export(exportList, refX, refY, refZ)
1564 function userComponentHolder.create()
1565 if not r2:checkAiQuota() then return end
1567 local function paramsCancel()
1568 debugInfo("Cancel form for 'User Component' creation")
1570 local function posOk(x, y, z)
1571 debugInfo(string.format("Validate creation of 'User Component' at pos (%d, %d, %d)", x, y, z))
1572 if r2.mustDisplayInfo("UserComponent") == 1 then
1573 r2.displayFeatureHelp("UserComponent")
1575 local component = r2.newComponent("UserComponentHolder")
1576 component.Base = r2.Translator.getDebugBase("palette.entities.botobjects.user_event")
1577 component.Name = r2:genInstanceName(i18n.get("uiR2EdUserComponent")):toUtf8()
1579 component.Position.x = x
1580 component.Position.y = y
1581 component.Position.z = r2:snapZToGround(x, y)
1583 r2:setCookie(component.InstanceId, "DisplayProp", 1)
1584 r2.requestInsertNode(r2:getCurrentAct().InstanceId, "Features", -1, "", component)
1587 local function posCancel()
1588 debugInfo("Cancel choice 'User Component' position")
1589 end
1590 local creature = r2.Translator.getDebugCreature("object_component_user_event.creature")
1591 r2:choosePos(creature, posOk, posCancel, "createUserComponent")
1594 feature.Components.DefaultFeature = {
1595 BaseClass="BaseClass",
1596 Name="DefaultFeature",
1597 --TreeIcon="r2ed_icon_default_feature.tga",
1598 DisplayerUI = "",
1599 Menu="ui:interface:r2ed_base_menu",
1600 Prop=
1602 {Name="Components", Type="Table"},
1604 ---------------------------------------------------------------------------------------------------------
1605 getFirstSelectableSon = function(this)
1606 for k = 0, this.Components.Size - 1 do
1607 if this.Components[k].Selectable then
1608 return this.Components[k]
1611 return nil
1612 end,
1613 ---------------------------------------------------------------------------------------------------------
1614 -- from base class
1615 appendInstancesByType = function(this, destTable, kind)
1616 assert(type(kind) == "string")
1617 --this:delegate():appendInstancesByType(destTable, kind)
1618 r2.Classes.BaseClass.appendInstancesByType(this, destTable, kind)
1619 for k, component in specPairs(this.Components) do
1620 component:appendInstancesByType(destTable, kind)
1622 end,
1623 -----------------------------------------------------------------------------------------------
1624 -- from base class
1625 hasScenarioCost = function(this)
1626 return true
1627 end,
1628 -----------------------------------------------------------------------------------------------
1629 -- from base class
1630 displayInSelectBar = function(this)
1631 return false
1632 end,
1634 pretranslate = r2.Translator.pretranslateDefaultFeature,
1635 pretranslate2 = r2.Translator.pretranslateDefaultFeature2,
1637 translate = r2.Translator.translateDefaultFeature,
1639 getAiCost = function(this)
1640 return r2.getAiCost(this) - 1
1641 end,
1643 getStaticObjectCost = function(this)
1644 return r2.getStaticObjectCost(this)
1649 function feature.Components.DefaultFeature.getActivitiesIds(this)
1650 return r2.Translator.getDefaultFeatureActivitiesIds(this)
1653 --- Npc
1654 local componentNpc = feature.Components.Npc
1656 ----------------------------------------------------------------------------
1657 -- add a line to the event menu
1658 function componentNpc.initLogicEntitiesMenu(this, logicEntityMenu, testApplicableAction)
1659 local name = i18n.get("uiR2EDnpc")
1660 local existPeople = nil
1662 local enumerator = r2:enumInstances("Npc")
1663 while 1 do
1664 local inst = enumerator:next()
1665 if not inst then break end
1666 local condExistPeople = not (inst:isKindOf("NpcCreature") or inst:isBotObject() or inst:isPlant())
1667 if not r2.events.memberManagement then --TEMP
1668 condExistPeople = not (inst:isKindOf("NpcCreature") or inst:isBotObject() or inst:isPlant() or inst:isGrouped()) --TEMP
1669 end --TEMP
1670 if condExistPeople then
1671 existPeople = inst
1672 break
1676 if existPeople and (not r2.events.memberManagement or testApplicableAction==nil or (testApplicableAction==true and r2.events:hasApplicableActions(existPeople))) then
1677 logicEntityMenu:addLine(name, "lua", "", "Npc")
1681 ----------------------------------------------------------------------------
1682 -- add a line to the event sub menu
1683 function componentNpc.initLogicEntitiesInstancesMenu(this, subMenu, calledFunction)
1684 local empty = true
1685 local enumerator = r2:enumInstances("Npc")
1686 while 1 do
1687 local entity = enumerator:next()
1688 if not entity then break end
1689 local addLine = not (entity:isKindOf("NpcCreature") or entity:isBotObject() or entity:isPlant())
1690 if not r2.events.memberManagement then --TEMP
1691 addLine = not (entity:isKindOf("NpcCreature") or entity:isBotObject() or entity:isPlant() or entity:isGrouped()) --TEMP
1692 end --TEMP
1693 if addLine then
1694 local uc_name = ucstring()
1695 uc_name:fromUtf8(entity.Name)
1696 subMenu:addLine(uc_name, "lua", calledFunction.."('".. entity.InstanceId .."')", entity.InstanceId)
1697 empty = false
1701 if empty==true then
1702 subMenu:addLine(i18n.get("uiR2EdNoSelelection"), "", "", "")
1706 ----------------------------------------------------------------------------
1707 -- add a line to the event menu
1708 function componentNpc:getLogicTranslations()
1710 local logicTranslations = {
1711 ["ApplicableActions"] = {
1712 ["Activate"] = {menu=i18n.get("uiR2EdActivates"):toUtf8(),
1713 text=r2:lowerTranslate("uiR2EdActivates")},
1714 ["Deactivate"] = {menu=i18n.get("uiR2EdDeactivates"):toUtf8(),
1715 text=r2:lowerTranslate("uiR2EdDeactivates")},
1716 ["Sit Down"] = {menu=i18n.get("uiR2EdSitDown"):toUtf8(),
1717 text=r2:lowerTranslate("uiR2EdSitsDown")},
1718 ["Stand Up"] = {menu=i18n.get("uiR2EdStandUp"):toUtf8(),
1719 text=r2:lowerTranslate("uiR2EdStandsUp")},
1720 ["Kill"] = {menu=i18n.get("uiR2EdKill"):toUtf8(),
1721 text=r2:lowerTranslate("uiR2EdKills")},
1722 ["begin activity sequence"] = {menu=i18n.get("uiR2EdBeginActivitySequ"):toUtf8(),
1723 text=r2:lowerTranslate("uiR2EdSequenceStarts")},
1724 ["Fight with player"] = {menu=i18n.get("uiR2EdFightWithPlayer"):toUtf8(),
1725 text=r2:lowerTranslate("uiR2EdFightWithPlayer")},
1726 ["Fight with Npcs"] = {menu=i18n.get("uiR2EdFightWithNpcs"):toUtf8(),
1727 text=r2:lowerTranslate("uiR2EdFightWithNpcs")},
1728 ["Dont fight with player"] = {menu=i18n.get("uiR2EdDontFightWithPlayer"):toUtf8(),
1729 text=r2:lowerTranslate("uiR2EdDontFightWithPlayer")},
1730 ["Dont fight with Npcs"] = {menu=i18n.get("uiR2EdDontFightWithNpcs"):toUtf8(),
1731 text=r2:lowerTranslate("uiR2EdDontFightWithNpcs")},
1732 ["Run"] = {menu=i18n.get("uiR2EdRun"):toUtf8(),
1733 text=r2:lowerTranslate("uiR2EdRun")},
1734 ["Dont run"] = {menu=i18n.get("uiR2EdDontRun"):toUtf8(),
1735 text=r2:lowerTranslate("uiR2EdDontRun")},
1738 ["Events"] = {
1739 ["activation"] = {menu=i18n.get("uiR2EdActivation"):toUtf8(),
1740 text=r2:lowerTranslate("uiR2EdActivation")},
1741 ["desactivation"] = {menu=i18n.get("uiR2EdDeactivation"):toUtf8(),
1742 text=r2:lowerTranslate("uiR2EdDeactivation")},
1743 ["death"] = {menu=i18n.get("uiR2EdDeath"):toUtf8(),
1744 text=r2:lowerTranslate("uiR2EdDeath")},
1745 ["end of activity step"] = {menu=i18n.get("uiR2EdEndActivityStep"):toUtf8(),
1746 text=r2:lowerTranslate("uiR2EdEndActivityStep")},
1747 ["end of activity sequence"] = {menu=i18n.get("uiR2EdEndActivitySequ"):toUtf8(),
1748 text=r2:lowerTranslate("uiR2EdEndActivitySequ")},
1749 ["begin of activity step"] = {menu=i18n.get("uiR2EdBeginActivityStep"):toUtf8(),
1750 text=r2:lowerTranslate("uiR2EdBeginActivityStep")},
1751 ["begin of activity sequence"] = {menu=i18n.get("uiR2EdBeginOfActivitySequ"):toUtf8(),
1752 text=r2:lowerTranslate("uiR2EdBeginOfActivitySequ")},
1753 ["targeted by player"] = {menu=i18n.get("uiR2EdTargetedByplayer"):toUtf8(),
1754 text=r2:lowerTranslate("uiR2EdTargetedByplayer")}
1757 ["Conditions"] = {
1758 ["is active"] = { menu=i18n.get( "uiR2Test0Spawned" ):toUtf8(),
1759 text=i18n.get( "uiR2Test1Spawned" ):toUtf8()},
1760 ["is inactive"] = { menu=i18n.get( "uiR2Test0Despawned" ):toUtf8(),
1761 text=i18n.get( "uiR2Test1Despawned" ):toUtf8()},
1762 ["is dead"] = { menu=i18n.get( "uiR2Test0Dead" ):toUtf8(),
1763 text=i18n.get( "uiR2Test1Dead" ):toUtf8()},
1764 ["is alive"] = { menu=i18n.get( "uiR2Test0Alive" ):toUtf8(),
1765 text=i18n.get( "uiR2Test1Alive" ):toUtf8()},
1766 ["is in activity sequence"] = { menu=i18n.get( "uiR2Test0Seq" ):toUtf8(),
1767 text=i18n.get( "uiR2Test1Seq" ):toUtf8()},
1768 ["is in activity step"] = { menu=i18n.get( "uiR2Test0Step" ):toUtf8(),
1769 text=i18n.get( "uiR2Test1Step" ):toUtf8()},
1772 return logicTranslations
1775 componentNpc.getLogicCondition = r2.Translator.getNpcLogicCondition
1776 componentNpc.getLogicAction = r2.Translator.getNpcLogicAction
1777 componentNpc.getLogicEvent = r2.Translator.getNpcLogicEvent
1779 -- obsolete
1780 feature.getCost = function (featureInstance)
1781 local cost = 0
1782 local components = featureInstance.Components
1784 local key,comp = next(components,nil)
1785 while(key ~= nil)
1788 if (comp.Class == "Npc" or comp.Class == "NpcCustom")
1789 then
1790 cost = cost +1
1792 key,comp = next(components,key)
1794 return cost
1797 -- obsolete
1798 feature.Translator = function (context)
1800 local components = context.Feature.Components
1801 --luaObject(context.Feature)
1802 local key,comp = next(components,nil)
1803 while(key ~= nil)
1805 -- Npc case (npc alone not object)
1806 if (comp.isKindOf and comp:isKindOf( "Npc"))
1807 then
1808 local hlNpc = comp
1810 context.Feature = hlNpc
1812 -- create and set rtNpc
1813 local rtNpc = r2.Translator.translateNpc(hlNpc, context)
1814 table.insert(context.RtAct.Npcs, rtNpc)
1816 -- create or get rtGrp
1817 -- set rtGrp.GroupParameter by reading hlNpc (Aggro, Player attackable..)
1818 local rtNpcGrp = r2.Translator.getRtGroup(context,hlNpc.InstanceId)
1819 r2.Translator.setGroupParameters(hlNpc, rtNpcGrp)
1820 --table.insert(context.RtAct.NpcGrps, rtNpcGrp)
1821 table.insert(rtNpcGrp.Children, rtNpc.Id)
1823 -- set activity
1824 local aiActivity = r2.Translator.getAiActivity(hlNpc)
1825 r2.Translator.translateActivities(context, hlNpc, hlNpc:getBehavior(), rtNpcGrp, aiActivity)
1827 -- set eventHandlers
1828 r2.Translator.translateEventHandlers(context, hlNpc, hlNpc:getBehavior().Actions, rtNpcGrp)
1831 key,comp = next(components,key)
1835 -- NpcCustom
1836 local componentNpcCustom = feature.Components.NpcCustom
1838 ----------------------------------------------------------------------------
1839 -- add no line to the event menu
1840 function componentNpcCustom.initLogicEntitiesMenu(this, logicEntityMenu)
1843 ----------------------------------------------------------------------------
1844 -- add a line to the event sub menu
1845 function componentNpcCustom.initLogicEntitiesInstancesMenu(this, subMenu, calledFunction)
1848 ----------------------------------------------------------------------------
1849 -- add a line to the event menu
1850 --function componentNpcCustom:getLogicTranslations()
1851 -- return {
1852 --end
1854 function componentNpcCustom.newCopy(this)
1855 local result = r2.Classes.BaseClass.newCopy(this)
1857 local sex
1858 if isR2PlayerMale(result.SheetClient) then
1859 sex = r2.male
1860 else
1861 sex = r2.female
1863 local race = getR2PlayerRace(result.SheetClient)
1865 result.Name = r2:randomNPCName2(race, sex)
1867 return result
1870 ---------------------------------------------------------------------------------------------------------
1871 -- Show the property window for this instance
1872 function componentNpcCustom.onShowProperties(this)
1873 local npcUI = getUI("ui:interface:r2ed_npc")
1874 assert(npcUI)
1876 if npcUI.active then
1877 r2:updateName()
1880 r2.Classes.BaseClass.onShowProperties(this)
1884 -- NpcCreature
1885 local componentNpcCreature = feature.Components.NpcCreature
1887 ----------------------------------------------------------------------------
1888 -- add no line to the event menu
1889 function componentNpcCreature.initLogicEntitiesMenu(this, logicEntityMenu, testApplicableAction)
1891 local name = i18n.get("uiR2EDCreatures")
1892 local existCreature = nil
1893 local enumerator = r2:enumInstances("NpcCreature")
1894 while 1 do
1895 local inst = enumerator:next()
1896 if not inst then break end
1897 local condExistCreature = not inst:isKindOf("NpcPlant")
1898 if not r2.events.memberManagement then --TEMP
1899 condExistCreature = not (inst:isKindOf("NpcPlant") or inst:isGrouped()) --TEMP
1900 end --TEMP
1901 if condExistCreature then
1902 existCreature = inst
1903 break
1907 if existCreature and (not r2.events.memberManagement or testApplicableAction==nil or (testApplicableAction==true and r2.events:hasApplicableActions(existCreature))) then
1908 logicEntityMenu:addLine(name, "lua", "", "NpcCreature")
1912 ----------------------------------------------------------------------------
1913 -- add a line to the event sub menu
1914 function componentNpcCreature.initLogicEntitiesInstancesMenu(this, subMenu, calledFunction)
1915 local empty = true
1916 local enumerator = r2:enumInstances("NpcCreature")
1917 while 1 do
1918 local entity = enumerator:next()
1919 if not entity then break end
1920 local addLine = not entity:isKindOf("NpcPlant")
1921 if not r2.events.memberManagement then
1922 addLine = not (entity:isKindOf("NpcPlant") or entity:isGrouped())
1923 end
1924 if addLine then
1925 local uc_name = ucstring()
1926 uc_name:fromUtf8(entity.Name)
1927 subMenu:addLine(uc_name, "lua", calledFunction.."('".. entity.InstanceId .."')", entity.InstanceId)
1928 empty = false
1932 if empty==true then
1933 subMenu:addLine(i18n.get("uiR2EdNoSelelection"), "", "", "")
1938 -- NpcPlant
1939 local componentNpcPlant = feature.Components.NpcPlant
1941 ----------------------------------------------------------------------------
1942 -- add no line to the event menu
1943 function componentNpcPlant.initLogicEntitiesMenu(this, logicEntityMenu)
1944 r2.Classes.LogicEntity.initLogicEntitiesMenu(this, logicEntityMenu)
1947 ----------------------------------------------------------------------------
1948 -- add a line to the event sub menu
1949 function componentNpcPlant.initLogicEntitiesInstancesMenu(this, subMenu, calledFunction)
1950 r2.Classes.LogicEntity.initLogicEntitiesInstancesMenu(this, subMenu, calledFunction)
1953 ----------------------------------------------------------------------------
1954 -- add a line to the event menu
1955 function componentNpcPlant:getLogicTranslations()
1956 local logicTranslations = {
1957 ["ApplicableActions"] = {
1958 ["Activate"] = {menu=i18n.get("uiR2EdActivates"):toUtf8(),
1959 text=r2:lowerTranslate("uiR2EdActivates")},
1960 ["Deactivate"] = {menu=i18n.get("uiR2EdDeactivates"):toUtf8(),
1961 text=r2:lowerTranslate("uiR2EdDeactivates")},
1962 ["Kill"] = {menu=i18n.get("uiR2EdKill"):toUtf8(),
1963 text=r2:lowerTranslate("uiR2EdKills")},
1966 ["Events"] = {
1967 ["activation"] = {menu=i18n.get("uiR2EdActivation"):toUtf8(),
1968 text=r2:lowerTranslate("uiR2EdActivation")},
1969 ["desactivation"] = {menu=i18n.get("uiR2EdDeactivation"):toUtf8(),
1970 text=r2:lowerTranslate("uiR2EdDeactivation")},
1971 ["death"] = {menu=i18n.get("uiR2EdDeath"):toUtf8(),
1972 text=r2:lowerTranslate("uiR2EdDeath")},
1973 ["targeted by player"] = {menu=i18n.get("uiR2EdTargetedByplayer"):toUtf8(),
1974 text=r2:lowerTranslate("uiR2EdTargetedByplayer")}
1976 ["Conditions"] = {
1977 ["is active"] = {menu=i18n.get("uiR2EdIsActive"):toUtf8(),
1978 text=r2:lowerTranslate("uiR2EdIsActive")},
1979 ["is dead"] = {menu=i18n.get("uiR2EdIsDead"):toUtf8(),
1980 text=r2:lowerTranslate("uiR2EdIsDead")},
1981 ["is alive"] = {menu=i18n.get("uiR2EdIsAlive"):toUtf8(),
1982 text=r2:lowerTranslate("uiR2EdIsAlive")},
1983 ["is inactive"] = {menu=i18n.get("uiR2EdIsInactive"):toUtf8(),
1984 text=r2:lowerTranslate("uiR2EdIsInactive")},
1987 return logicTranslations
1994 return feature
1997 r2.Features["DefaultFeature"] = registerFeature()
2004 --------------------------------------------------------------------------------------------------
2005 -------------------------- ACTIVE LOGIC ENTITY DisplayerProperties -----------------------------------------
2006 --------------------------------------------------------------------------------------------------
2008 local activeLogicEntityPropertySheetDisplayerTable = clone(r2:propertySheetDisplayer())
2010 ------------------------------------------------
2011 function activeLogicEntityPropertySheetDisplayerTable:onPostCreate(instance)
2013 ------------------------------------------------
2014 function activeLogicEntityPropertySheetDisplayerTable:onErase(instance)
2015 r2:logicEntityPropertySheetDisplayer():onErase(instance)
2017 ------------------------------------------------
2018 function activeLogicEntityPropertySheetDisplayerTable:onPreHrcMove(instance)
2020 ------------------------------------------------
2021 function activeLogicEntityPropertySheetDisplayerTable:onPostHrcMove(instance)
2023 ------------------------------------------------
2024 function activeLogicEntityPropertySheetDisplayerTable:onFocus(instance, hasFocus)
2027 ------------------------------------------------
2028 r2.activitiesAndChatsUIUpdate = false
2029 function activeLogicEntityPropertySheetDisplayerTable:onSelect(instance, isSelected)
2031 r2:logicEntityPropertySheetDisplayer():onSelect(instance, isSelected)
2033 if not isSelected or (instance.Ghost == true) then
2035 r2.activities:closeEditor()
2036 r2.miniActivities:closeEditor()
2037 else
2038 if instance:isKindOf("Npc") then
2039 local helpButton = getUI("ui:interface:r2ed_property_sheet_Npc:header_opened:help")
2040 assert(helpButton)
2041 if instance:isBotObject() then
2042 debugInfo("1")
2043 helpButton.active = false
2044 helpButton.parent.parent.title_delta_max_w = r2.DefaultPropertySheetTitleClampSize
2045 else
2046 debugInfo("2")
2047 helpButton.active = true
2048 helpButton:updateCoords()
2049 helpButton.parent.parent.title_delta_max_w = r2.DefaultPropertySheetTitleClampSize - helpButton.w_real - 4
2052 r2.activities.isInitialized = false
2053 r2.miniActivities:openEditor()
2057 ------------------------------------------------
2058 function activeLogicEntityPropertySheetDisplayerTable:onAttrModified(instance, attributeName)
2060 r2:logicEntityPropertySheetDisplayer():onAttrModified(instance, attributeName)
2062 if attributeName == "Name" then
2064 if r2.events.filteredLogicEntityId == instance.InstanceId then
2065 r2.events:updateSequenceUI()
2068 if not r2.activitiesAndChatsUIUpdate or instance ~= r2:getSelectedInstance() then
2069 return
2072 local activitiesUI = getUI(r2.activities.uiId)
2073 assert(activitiesUI)
2074 local dialogsUI = getUI(r2.dialogs.uiId)
2075 assert(dialogsUI)
2077 activitiesUI.uc_title = i18n.get("uiR2EDActivitySequenceEditor"):toUtf8() .. instance[attributeName]
2078 dialogsUI.uc_title = i18n.get("uiR2EDChatSequenceEditor"):toUtf8() .. instance[attributeName]
2080 end
2082 ------------------------------------------------
2083 function r2:activeLogicEntityPropertySheetDisplayer()
2084 return activeLogicEntityPropertySheetDisplayerTable -- returned shared displayer to avoid wasting memory