6 -- The fauna feature contains 2 herds of creatures (herbivores and carnivores) that wander between 2 life zones (sleep zone and
7 -- food zone).There are 2 differents kinds of components in this feature: fauna system and creature.
8 -- The fauna system component is some kind of manager for the feature. It creates the creatures and their life zones, and then
9 -- store them in its components table, so that their createChostComponents call and translation are automatically done by
11 -- The created life zones are affected to each of the creature components. But the properties panel of the creature components allows
12 -- the DM to choose other zones in the scenario through RefId picking.
15 r2
.Features
.FaunaFeature
= {}
17 local feature
= r2
.Features
.FaunaFeature
19 feature
.Name
="FaunaFeature"
21 feature
.Description
="Generates a pack of carnivores and a herd of herbivores that will wander between two life zones (sleep zone, food zone) each."
23 feature
.Components
= {}
26 -- *********************
27 -- * FEATURE FUNCTIONS *
28 -- *********************
33 -- Reinit makes sure the enums are reinitialized, ie contain all creatures (respectively herbivores or carnivores) from
34 -- the desert ecosystem and with a level between 1 and 50.
35 local function reinit(form
, creature
)
37 debugInfo("Reinit impossible: nil form")
41 local creatureEnum
= form
:find(creature
.."Race")
42 if creatureEnum
== nil then
43 debugInfo("Reinit impossible: can't find "..creature
.."Race enum")
46 creatureEnum
:resetTexts()
48 local creaturePalette
= {}
49 if creature
== "Carnivore" then
50 creaturePalette
= r2
.Palette
.Entries
.creature
.creatures_predators
.instances
52 creaturePalette
= r2
.Palette
.Entries
.creature
.creatures_passive
.instances
55 local k
, v
= next(creaturePalette
, nil)
57 if r2
.isInPalette(v
.Id
) then
58 local paletteElt
= r2
.getPaletteElement(v
.Id
)
59 if paletteElt
and paletteElt
.RingAccess
and
60 r2
.RingAccess
.testAccess(paletteElt
.RingAccess
) then
62 if paletteElt
.Ecosystem
== "Desert" and paletteElt
.Level
>= 1 and paletteElt
.Level
<= 50 then
63 creatureEnum
:addText(ucstring(i18n
.get(v
.Translation
)))
67 k
, v
= next(creaturePalette
, k
)
71 -- Returns the chosen bases from the form before creating the components.
72 local function getBase(creature
, form
)
74 debugInfo("getBase: form is nil")
78 local creaturePalette
= {}
79 if creature
== "Carnivore" then
80 creaturePalette
= r2
.Palette
.Entries
.creature
.creatures_predators
.instances
82 creaturePalette
= r2
.Palette
.Entries
.creature
.creatures_passive
.instances
85 local creatureEnum
= form
:find(creature
.."Race")
86 local race
= creatureEnum
.selection_text
88 local k
, v
= next(creaturePalette
, nil)
90 local name
= i18n
.get(v
.Translation
):toUtf8()
94 k
, v
= next(creaturePalette
, k
)
98 -- When the selected ecosystem or level changes, the corresponding creature combobox is updated.
99 local function updateEnum(creature
)
100 local currentForm
= r2
.CurrentForm
101 if (currentForm
== nil) then
102 debugInfo("UpdatePredators: r2.CurrentForm is nil")
106 local creatureEnum
= currentForm
:find(creature
.."Race")
107 local ecoEnum
= currentForm
:find(creature
.."Ecosystem")
108 local currentEco
= ecoEnum
.selection_text
109 if currentEco
== "Lakes" then
110 currentEco
= "Lacustre"
113 local levelEnum
= currentForm
:find(creature
.."Level")
114 local levelRange
= levelEnum
.selection
+ 1
117 if levelRange
== 0 then
121 levelMin
= (levelRange
- 1) * 50 + 1
122 levelMax
= levelMin
+ 49
125 creatureEnum
:resetTexts()
127 local creaturePalette
= {}
128 if creature
== "Carnivore" then
129 creaturePalette
= r2
.Palette
.Entries
.creature
.creatures_predators
.instances
131 creaturePalette
= r2
.Palette
.Entries
.creature
.creatures_passive
.instances
134 local k
, v
= next(creaturePalette
, nil)
136 if r2
.isInPalette(v
.Id
) then
137 local paletteElt
= r2
.getPaletteElement(v
.Id
)
138 if paletteElt
and paletteElt
.RingAccess
and
139 r2
.RingAccess
.testAccess(paletteElt
.RingAccess
) then
140 if paletteElt
.Ecosystem
== currentEco
and paletteElt
.Level
>= levelMin
and paletteElt
.Level
<= levelMax
then
141 creatureEnum
:addText(ucstring(i18n
.get(v
.Translation
)))
145 k
, v
= next(creaturePalette
, k
)
149 -- Calls update function for the carnivores combobox.
150 local function updateCarnivores(form
)
151 updateEnum("Carnivore")
154 -- Calls update function for the herbivores combobox.
155 local function updateHerbivores(form
)
156 updateEnum("Herbivore")
159 local function resetForm()
161 local currentForm
= r2
:getForm("Fauna_Form")
165 local creature
= "Carnivore"
166 local ecoEnum
= currentForm
:find(creature
.."Ecosystem")
167 ecoEnum
.selection_text
= "Desert"
168 local levelEnum
= currentForm
:find(creature
.."Level")
169 levelEnum
.selection
= 0
170 updateCarnivores(form
)
173 local creature
= "Herbivore"
174 local ecoEnum
= currentForm
:find(creature
.."Ecosystem")
175 ecoEnum
.selection_text
= "Desert"
176 local levelEnum
= currentForm
:find(creature
.."Level")
177 levelEnum
.selection
= 0
178 updateHerbivores(form
)
183 -- The creation form lets the DM choose the type of creatures and their number.
184 -- Like the palette tree, the available creatures are filtered by their ecosystems and level.
185 -- Each life cycle duration is defined in the properties panel of the creature component.
186 -- The creation form will return the chosen creature base when ok button is pressed.
187 -- The form is reinitialized each time the ok or cancel button is pressed.
189 feature
.registerForms
= function()
191 -- Initializes the creature comboboxes. Default ecosystem is desert and default level range is 1-50.
192 local function init(creature
)
195 local creaturePalette
= {}
196 if not r2
.Palette
.Entries
.creature
then
197 return -- special case for the 'light' palette
199 if creature
== "Carnivore" then
200 creaturePalette
= r2
.Palette
.Entries
.creature
.creatures_predators
.instances
202 creaturePalette
= r2
.Palette
.Entries
.creature
.creatures_passive
.instances
204 local k
, v
= next(creaturePalette
, nil)
206 if r2
.isInPalette(v
.Id
) then
207 local paletteElt
= r2
.getPaletteElement(v
.Id
)
209 if paletteElt
.Ecosystem
== "Desert" and paletteElt
.Level
>= 1 and paletteElt
.Level
<= 50 then
210 table.insert(initEnum
, i18n
.get(v
.Translation
))
214 k
, v
= next(creaturePalette
, k
)
220 r2
.Forms
.Fauna_Form
=
222 Caption
= "uiR2EdFauna",
225 {Name
="CarnivoresCount", Type
="Number", Category
="uiR2EDRollout_Carnivores", Min
="1", Max
="12", Default
="3", Translation
="uiR2EDProp_Count"},
226 {Name
="CarnivoreRace", Type
="Number", Category
="uiR2EDRollout_Carnivores", WidgetStyle
="EnumDropDown", Translation
="uiR2EDProp_Race",
227 Enum
= init("Carnivore")
229 {Name
="CarnivoreEcosystem", Type
="Number", Category
="uiR2EDRollout_Carnivores", WidgetStyle
="EnumDropDown", Translation
="uiR2EDProp_Ecosystem",
230 Enum
={"Desert", "Forest", "Jungle", "Lakes", "PrimeRoots", "Goo"},
231 onChange
= updateCarnivores
233 {Name
="CarnivoreLevel", Type
="Number", Category
="uiR2EDRollout_Carnivores", WidgetStyle
="EnumDropDown", Translation
="uiR2EDProp_Level",
234 Enum
={"1-50", "51-100", "101-150", "151-200", "201-250"},
235 onChange
= updateCarnivores
237 {Name
="HerbivoresCount", Type
="Number", Category
="uiR2EDRollout_Herbivores", Min
="1", Max
="12", Default
="7", Translation
="uiR2EDProp_Count"},
238 {Name
="HerbivoreRace", Type
="Number", Category
="uiR2EDRollout_Herbivores", WidgetStyle
="EnumDropDown", Translation
="uiR2EDProp_Race",
239 Enum
= init("Herbivore")
241 {Name
="HerbivoreEcosystem", Type
="Number", Category
="uiR2EDRollout_Herbivores", WidgetStyle
="EnumDropDown", Translation
="uiR2EDProp_Ecosystem",
242 Enum
={"Desert", "Forest", "Jungle", "Lakes", "PrimeRoots", "Goo"},
243 onChange
= updateHerbivores
245 {Name
="HerbivoreLevel", Type
="Number", Category
="uiR2EDRollout_Herbivores", WidgetStyle
="EnumDropDown", Translation
="uiR2EDProp_Level",
246 Enum
={"1-50", "51-100", "101-150", "151-200", "201-250"},
247 onChange
= updateHerbivores
258 local FaunaRegionRadius
= 5
261 -----------------------------------------------------------------------------------------------
262 -- CREATURE COMPONENT
264 feature
.Components
.Creature
=
266 BaseClass
="LogicEntity",
268 Menu
="ui:interface:r2ed_feature_menu",
270 DisplayerUI
= "R2::CDisplayerLua",
271 DisplayerUIParams
= "defaultUIDisplayer",
272 DisplayerVisual
= "R2::CDisplayerVisualEntity",
273 -----------------------------------------------------------------------------------------------
276 ApplicableActions
= {},
287 -----------------------------------------------------------------------------------------------
290 {Name
="InstanceId", Type
="String", WidgetStyle
="StaticText", Visible
= false},
291 {Name
="Components", Type
="Table", Visible
= false},
292 {Name
="Ghosts", Type
= "Table", Visible
= false },
293 {Name
="Name", Type
="String", MaxNumChar
="32"},
294 {Name
="CrittersCount", Type
="String", WidgetStyle
="StaticText", Translation
="uiR2EDProp_CrittersCount"},
295 {Name
="RaceBase", Type
="String", WidgetStyle
="StaticText", Visible
=false},
296 {Name
="RaceName", Type
="String", WidgetStyle
="StaticText", Translation
="uiR2EDProp_Race"},
297 {Name
="SleepZone", Type
="RefId", PickFuntion
= "r2:canPickZone", SetRefIdFunction
= "r2:setZoneRefIdTarget", Translation
="uiR2EDProp_SleepZone"},
298 {Name
="FoodZone", Type
="RefId", PickFuntion
= "r2:canPickZone", SetRefIdFunction
= "r2:setZoneRefIdTarget", Translation
="uiR2EDProp_FoodZone"},
299 {Name
="FoodDuration", Type
="Number", Category
="uiR2EDRollout_LifeCyclesInSeconds", Min
="1", Max
="40000", Default
="30", Translation
="uiR2EDProp_FoodDuration"},
300 {Name
="SleepDuration", Type
="Number", Category
="uiR2EDRollout_LifeCyclesInSeconds", Min
="1", Max
="40000", Default
="30", Translation
="uiR2EDProp_SleepDuration"},
304 getAvailableCommands
= function(this
, dest
)
305 r2
.Classes
.LogicEntity
.getAvailableCommands(this
, dest
) -- fill by ancestor
306 this
:getAvailableDisplayModeCommands(dest
)
309 appendInstancesByType
= function(this
, destTable
, kind
)
310 assert(type(kind
) == "string")
311 r2
.Classes
.LogicEntity
.appendInstancesByType(this
, destTable
, kind
)
312 for k
, component
in specPairs(this
.Components
) do
313 component
:appendInstancesByType(destTable
, kind
)
317 getSelectBarSons
= function(this
)
321 canHaveSelectBarSons
= function(this
)
325 onPostCreate
= function(this
)
326 this
:createGhostComponents()
329 translate
= function(this
, context
)
330 --local rtNpcGrp = r2.Translator.getRtGroup(context, context.Feature.InstanceId)
331 --local aiState = r2.newComponent("RtAiState")
332 --aiState.AiActivity = "normal"
333 --table.insert(context.RtAct.AiStates, aiState)
334 --table.insert(aiState.Children, rtNpcGrp.Id)
335 --local rtNpcGrp = r2.Translator.getRtGroup(context, this.InstanceId)
336 --r2.Translator.translateEventHandlers( context, this, this.Behavior.Actions, rtNpcGrp)
337 r2
.Translator
.translateAiGroup(this
, context
)
341 pretranslate
= function(this
, context
)
342 --local instance = r2:getInstanceFromId(context.Feature.InstanceId);
343 --r2.Translator.registerManager(context, context.Feature)
345 r2
.Translator
.createAiGroup(this
, context
)
349 local component
= feature
.Components
.Creature
351 component
.getLogicAction
= function(entity
, context
, action
)
355 component
.getLogicCondition
= function(this
, context
, condition
)
359 component
.getLogicEvent
= function(this
, context
, event
)
363 function component
:getLogicTranslations()
365 local logicTranslations
= {
366 ["ApplicableActions"] = {},
369 return nil--logicTranslations
372 component
.createGhostComponents
= function(this
, act
)
379 herd
= r2
.newComponent("NpcGrpFeature")
382 if comp
._Seed
then math
.randomseed(comp
._Seed
) end
385 local x
= comp
.Position
.x
386 local y
= comp
.Position
.y
387 local n
= comp
._CrittersCount
388 local pas
= (2 * math
.pi
)/n
389 local r
= (n
/(2*math
.pi
))+2
391 local npc
= r2
.newComponent("Npc")
392 npc
.Name
= comp
.RaceName
393 npc
.Base
= comp
.RaceBase
--"palette.entities.creatures.cbadc1"
396 local rr
= FaunaRegionRadius
- 1--r + math.random() * 5
397 npc
.Position
.x
= (rr
-1) * math
.cos((i
-1)*pas
)
398 npc
.Position
.y
= (rr
-1) * math
.sin((i
-1)*pas
)
400 npc
.Angle
= 2 * math
.pi
* math
.random(0, 100)/100.0
403 local manager
= r2
:getInstanceFromId(comp
.ManagerId
)
405 if manager
.Active
== 1 then npc
.AutoSpawn
= 1 else npc
.AutoSpawn
= 0 end
407 r2
.requestSetGhostNode(comp
.InstanceId
, "_LeaderId",npc
.InstanceId
)
408 isHerbivore
= r2
.getPropertyValue(npc
, "IsHerbivore")
411 if act
then -- TestMode --
412 table.insert(herd
.Components
, npc
)
414 r2
.requestInsertGhostNode(this
.InstanceId
, "Ghosts", -1, "", npc
)
415 r2
:getInstanceFromId(npc
.InstanceId
).Selectable
= false
420 -- 2 wander sequences corresponding to the activities in both life zones attached to the herd
422 local sequence
= r2
.newComponent("ActivitySequence")
425 table.insert(leader
.Behavior
.Activities
, sequence
)
427 sequence
.Name
= "Life Cycle"
428 sequence
.Repeating
= 1
430 -- Wander in sleep zone
431 local step
= r2
.newComponent("ActivityStep")
432 table.insert(sequence
.Components
, step
)
434 step
.Name
= "Rest In Zone"
435 step
.Activity
= "Rest In Zone"
436 step
.ActivityZoneId
= r2
.RefId(comp
.SleepZone
)
438 step
.TimeLimit
= "Few Sec"
439 step
.TimeLimitValue
= tostring(comp
.SleepDuration
)
441 -- Wander in food zone
442 local step
= r2
.newComponent("ActivityStep")
443 table.insert(sequence
.Components
, step
)
446 if isHerbivore
== 1 then
447 step
.Name
= "Feed In Zone"
448 step
.Activity
= "Feed In Zone"
450 step
.Name
= "Hunt In Zone"
451 step
.Activity
= "Hunt In Zone"
453 step
.ActivityZoneId
= r2
.RefId(comp
.FoodZone
)
455 step
.TimeLimit
= "Few Sec"
456 step
.TimeLimitValue
= tostring(comp
.FoodDuration
)
461 comp
.User
._Herd
= herd
.InstanceId
462 --herd.Name = r2:genInstanceName(i18n.get("uiR2EdFaunaFeature")):toUtf8()
464 herd
.Position
.x
= comp
.Position
.x
465 herd
.Position
.y
= comp
.Position
.y
466 r2
.requestInsertGhostNode(act
.InstanceId
, "Features", -1, "", herd
)
471 component
.createComponent
= function(x
, y
, nbcritters
, raceBase
, raceName
,
472 sleepZoneId
, foodZoneId
)
475 local comp
= r2
.newComponent("Creature")
478 --comp.Base = "palette.entities.botobjects.user_event"
479 comp
.Base
= r2
.Translator
.getDebugBase("palette.entities.botobjects.user_event")
481 comp
.Name
= r2
:genInstanceName(i18n
.get("uiR2EdCreatureComponent")):toUtf8()
485 comp
.Position
.z
= r2
:snapZToGround(x
, y
)
487 comp
._CrittersCount
= nbcritters
488 comp
.CrittersCount
= tostring(nbcritters
)
489 comp
.RaceBase
= raceBase
490 comp
.RaceName
= raceName
492 comp
.SleepDuration
= 30
493 comp
.FoodDuration
= 30
495 comp
._Seed
= os
.time()
497 comp
.SleepZone
= sleepZoneId
498 comp
.FoodZone
= foodZoneId
503 -----------------------------------------------------------------------------------------------
504 -- FAUNA SYSTEM COMPONENT
505 -- Fauna system containing 2 Creature components (herbivores & carnivores) and 3 life zones.
506 feature
.Components
.Fauna
=
508 BaseClass
="LogicEntity",
510 Menu
="ui:interface:r2ed_feature_menu",
513 DisplayerUI
= "R2::CDisplayerLua",
514 DisplayerUIParams
= "defaultUIDisplayer",
515 DisplayerVisual
= "R2::CDisplayerVisualEntity",
516 -----------------------------------------------------------------------------------------------
519 ApplicableActions
= {"activate", "deactivate"},
521 Events
= {"deactivation", "activation"},
523 Conditions
= {"is active", "is inactive"},
530 -----------------------------------------------------------------------------------------------
533 {Name
="InstanceId", Type
="String", WidgetStyle
="StaticText", Visible
= false},
534 {Name
="Components", Type
="Table", Visible
= false},
535 {Name
="Ghosts", Type
= "Table", Visible
= false },
536 {Name
="Name", Type
="String", MaxNumChar
="32"},
537 {Name
="Active", Type
= "Number", WidgetStyle
="Boolean", DefaultValue
="1" },
538 {Name
="CarnivoresCount", Type
="String", Category
="uiR2EDRollout_Carnivores", WidgetStyle
="StaticText", Translation
="uiR2EDProp_Count"},
539 {Name
="CarnivoreBase", Type
="String", Category
="uiR2EDRollout_Carnivores", WidgetStyle
="StaticText", Visible
= false},
540 {Name
="CarnivoreRace", Type
="String", Category
="uiR2EDRollout_Carnivores", WidgetStyle
="StaticText", Translation
="uiR2EDProp_Race"},
541 {Name
="HerbivoresCount", Type
="String", Category
="uiR2EDRollout_Herbivores", WidgetStyle
="StaticText",Translation
="uiR2EDProp_Count"},
542 {Name
="HerbivoreBase", Type
="String", Category
="uiR2EDRollout_Herbivores", WidgetStyle
="StaticText", Visible
= false},
543 {Name
="HerbivoreRace", Type
="String", Category
="uiR2EDRollout_Herbivores", WidgetStyle
="StaticText", Translation
="uiR2EDProp_Race"},
546 getParentTreeNode
= function(this
)
547 return this
:getFeatureParentTreeNode()
550 getAvailableCommands
= function(this
, dest
)
551 r2
.Classes
.LogicEntity
.getAvailableCommands(this
, dest
) -- fill by ancestor
552 this
:getAvailableDisplayModeCommands(dest
)
555 appendInstancesByType
= function(this
, destTable
, kind
)
556 assert(type(kind
) == "string")
557 r2
.Classes
.LogicEntity
.appendInstancesByType(this
, destTable
, kind
)
558 for k
, component
in specPairs(this
.Components
) do
559 component
:appendInstancesByType(destTable
, kind
)
563 getSelectBarSons
= function(this
)
567 canHaveSelectBarSons
= function(this
)
571 onPostCreate
= function(this
)
572 --this:createGhostComponents()
573 if this
.User
.DisplayProp
and this
.User
.DisplayProp
== 1 then
574 r2
:setSelectedInstanceId(this
.InstanceId
)
575 r2
:showProperties(this
)
576 this
.User
.DisplayProp
= nil
580 translate
= function(this
, context
)
581 r2
.Translator
.translateAiGroup(this
, context
)
582 r2
.Translator
.translateFeatureActivation(this
, context
)
585 pretranslate
= function(this
, context
)
586 r2
.Translator
.createAiGroup(this
, context
)
590 component
= feature
.Components
.Fauna
593 local FaunaRegionNumCorners
= 6
594 --local FaunaRegionRadius = 5
595 local FaunaRegionOffsets
= { { x
= 10, y
= 0 }, { x
= -7, y
= -7}, { x
= 0, y
= 10} }
598 component
.create
= function()
599 if not r2
:checkAiQuota() then return end
601 local function paramsOk(resultTable
, form
)
604 local carnivoreBase
, carnivoreName
= getBase("Carnivore", form
)
605 local herbivoreBase
, herbivoreName
= getBase("Herbivore", form
)
607 local x
= tonumber( resultTable
["X"] )
608 local y
= tonumber( resultTable
["Y"] )
610 local carnCount
= tonumber(resultTable
["CarnivoresCount"])
611 local herbCount
= tonumber(resultTable
["HerbivoresCount"])
614 if not r2
:checkAiQuota(carnCount
+ herbCount
+ 1) then return end
617 if not x
or not y
or not carnivoreBase
or not carnivoreName
or not carnCount
or not herbivoreBase
618 or not herbivoreName
or not herbCount
620 r2
:doForm("Fauna_Form", resultTable
, paramsOk
, paramsCancel
)
623 printMsg("FaunaSystem: Failed to create component either because your scenario is full or because you don't yet have access to creatures of the level and ecosystem that you have selected")
627 r2
.requestNewAction(i18n
.get("uiR2EDNewFaunaFeatureAction"))
628 local component
= feature
.Components
.Fauna
.createComponent(x
, y
, carnCount
, carnivoreBase
, carnivoreName
,
629 herbCount
, herbivoreBase
, herbivoreName
)
630 r2
:setCookie(component
.InstanceId
, "DisplayProp", 1)
631 r2
.requestInsertNode(r2
:getCurrentAct().InstanceId
, "Features", -1, "", component
)
635 local function paramsCancel(data
, form
)
638 local function posOk(x
, y
, z
)
639 debugInfo(string.format("Validate creation of 'FaunaFeature' at pos (%d, %d, %d)", x
, y
, z
))
640 if r2
.mustDisplayInfo("Fauna") == 1 then
641 r2
.displayFeatureHelp("Fauna")
643 r2
:doForm("Fauna_Form", {X
=x
, Y
=y
}, paramsOk
, paramsCancel
)
646 local function posCancel()
647 debugInfo("Cancel choice 'FaunaFeature' position")
649 --r2:choosePos("object_component_user_event.creature", posOk, posCancel, "createFeatureFauna")
650 local creature
= r2
.Translator
.getDebugCreature("object_component_user_event.creature")
651 --r2:choosePos(creature, posOk, posCancel, "createFeatureFauna")
654 for p
= 1, table.getn(FaunaRegionOffsets
) do
656 local step
= 2 * math
.pi
/ FaunaRegionNumCorners
657 for k
= 0, FaunaRegionNumCorners
- 1 do
658 table.insert(poly
, CVector2f(FaunaRegionOffsets
[p
].x
+ FaunaRegionRadius
* math
.cos(k
* step
),
659 FaunaRegionOffsets
[p
].y
+ FaunaRegionRadius
* math
.sin(k
* step
)))
661 table.insert(polys
, poly
)
663 r2
:choosePos(creature
, posOk
, posCancel
, "createFeatureFauna",
666 polys
, r2
.PrimRender
.ComponentRegionLook
, r2
.PrimRender
.ComponentRegionInvalidLook
)
669 function component
.getAiCost(this
)
670 if this
.User
.GhostDuplicate
then return 0 end
671 return r2
.getAiCost(this
) - 2
678 -- create the fauna system component by creating and inserting zones and creature component into its own components table.
679 -- Generates a sleep zone and a food zone for the herbivores, and a sleep zone for the carnivores. The carnivore hunt zone is
680 -- one of the herbivore zones (default is herbivore sleep zone).
682 component
.createComponent
= function(x
, y
, carnCount
, carnivoreBase
, carnivoresName
,
683 herbCount
, herbivoreBase
, herbivoresName
)
685 local comp
= r2
.newComponent("Fauna")
688 --TODO: replace this milestone base by some default feature base
689 comp
.Base
= "palette.entities.botobjects.user_event"
691 comp
.Name
= r2
:genInstanceName(i18n
.get("uiR2EdFaunaFeature")):toUtf8()
695 comp
.Position
.z
= r2
:snapZToGround(x
, y
)
697 comp
._CarnCount
= carnCount
698 comp
.CarnivoresCount
= tostring(carnCount
)
699 comp
.CarnivoreBase
= carnivoreBase
700 comp
.CarnivoreRace
= tostring(carnivoresName
)
702 comp
._HerbCount
= herbCount
703 comp
.HerbivoresCount
= tostring(herbCount
)
704 comp
.HerbivoreBase
= herbivoreBase
705 comp
.HerbivoresName
= herbivoresName
706 comp
.HerbivoreRace
= tostring(herbivoresName
)
708 comp
._Seed
= os
.time()
710 -- Herbivore sleep zone
711 local zoneSleep1
= r2
.newComponent("Region")
712 r2
.Utils
.createRegion(zoneSleep1
, 0, 0, FaunaRegionRadius
, FaunaRegionNumCorners
)
713 zoneSleep1
.Deletable
= 1
714 zoneSleep1
.Position
.x
= comp
.Position
.x
+ FaunaRegionOffsets
[1].x
715 zoneSleep1
.Position
.y
= comp
.Position
.y
+ FaunaRegionOffsets
[1].y
716 zoneSleep1
.Position
.z
= comp
.Position
.z
717 zoneSleep1
.InheritPos
= 0
718 zoneSleep1
.Name
= r2
:genInstanceName(i18n
.get("uiR2EDNameSleepRegion")):toUtf8()
719 table.insert(comp
.Components
, zoneSleep1
)
721 -- Carnivore sleep zone
722 local zoneSleep2
= r2
.newComponent("Region")
723 r2
.Utils
.createRegion(zoneSleep2
, 0, 0, FaunaRegionRadius
, FaunaRegionNumCorners
)
724 zoneSleep2
.Deletable
= 1
725 zoneSleep2
.Position
.x
= comp
.Position
.x
+ FaunaRegionOffsets
[2].x
726 zoneSleep2
.Position
.y
= comp
.Position
.y
+ FaunaRegionOffsets
[2].y
727 zoneSleep2
.Position
.z
= comp
.Position
.z
728 zoneSleep2
.InheritPos
= 0
729 zoneSleep2
.Name
= r2
:genInstanceName(i18n
.get("uiR2EDNameSleepRegion")):toUtf8()
730 table.insert(comp
.Components
, zoneSleep2
)
732 --Herbivore sleep zone
733 local zoneFood
= r2
.newComponent("Region")
734 r2
.Utils
.createRegion(zoneFood
, 0, 0, FaunaRegionRadius
, FaunaRegionNumCorners
)
735 zoneFood
.Deletable
= 1
736 zoneFood
.Position
.x
= comp
.Position
.x
+ FaunaRegionOffsets
[3].x
737 zoneFood
.Position
.y
= comp
.Position
.y
+ FaunaRegionOffsets
[3].y
738 zoneFood
.Position
.z
= comp
.Position
.z
739 zoneFood
.InheritPos
= 0
740 zoneFood
.Name
= r2
:genInstanceName(i18n
.get("uiR2EDNameFoodRegion")):toUtf8()
741 table.insert(comp
.Components
, zoneFood
)
743 -- Herd of herbivores
744 local herbivores
= feature
.Components
.Creature
.createComponent(zoneSleep1
.Position
.x
, zoneSleep1
.Position
.y
, herbCount
, herbivoreBase
,
745 herbivoresName
, zoneSleep1
.InstanceId
, zoneFood
.InstanceId
)
746 herbivores
.Name
= i18n
.get("uiR2EdHerbivores"):toUtf8()
747 --herbivores.Position.x = zoneSleep1.Position.x--comp.Position.x + 10
748 --herbivores.Position.y = zoneSleep1.Position.y--comp.Position.y + 10
749 herbivores
.InheritPos
= 0
750 --herbivores.Active = comp.Active
751 herbivores
.ManagerId
= comp
.InstanceId
752 table.insert(comp
.Components
, herbivores
)
753 comp
._HerbId
= herbivores
.InstanceId
755 -- Pack of carnivores
756 local carnivores
= feature
.Components
.Creature
.createComponent(zoneSleep2
.Position
.x
, zoneSleep2
.Position
.y
, carnCount
, carnivoreBase
,
757 carnivoresName
, zoneSleep2
.InstanceId
, zoneSleep1
.InstanceId
)
758 carnivores
.Name
= i18n
.get("uiR2EdCarnivores"):toUtf8()
759 carnivores
.InheritPos
= 0
760 carnivores
.ManagerId
= comp
.InstanceId
761 table.insert(comp
.Components
, carnivores
)
762 comp
._CarnId
= carnivores
.InstanceId
767 component
.getLogicAction
= function(entity
, context
, action
)
768 assert( action
.Class
== "ActionStep")
769 local component
= r2
:getInstanceFromId(action
.Entity
)
771 local rtNpcGrp
= r2
.Translator
.getRtGroup(context
, component
.InstanceId
)
774 local herbi
= r2
:getInstanceFromId(component
._HerbId
)
776 local herbivores
= r2
:getInstanceFromId(herbi
.User
._Herd
)
778 local rtHerbiGrp
= r2
.Translator
.getRtGroup(context
, herbivores
.InstanceId
)
781 local carni
= r2
:getInstanceFromId(component
._CarnId
)
783 local carnivores
= r2
:getInstanceFromId(carni
.User
._Herd
)
785 local rtCarniGrp
= r2
.Translator
.getRtGroup(context
, carnivores
.InstanceId
)
789 if action
.Action
.Type
== "deactivate" then
790 local action1
= r2
.Translator
.createAction("set_value", rtNpcGrp
.Id
, "Active", 0)
791 local action2
= r2
.Translator
.getNpcLogicActionDeactivate(herbivores
, context
, action
, rtHerbiGrp
)
792 local action3
= r2
.Translator
.getNpcLogicActionDeactivate(carnivores
, context
, action
, rtCarniGrp
)
793 local action4
= r2
.Translator
.createAction("user_event_trigger", rtNpcGrp
.Id
, 5)
794 local multiaction
= r2
.Translator
.createAction("multi_actions", {action1
, action2
, action3
, action4
})
795 return multiaction
, multiaction
796 elseif (action
.Action
.Type
== "activate") then
797 local action1
= r2
.Translator
.createAction("set_value", rtNpcGrp
.Id
, "Active", 1)
798 local action2
= r2
.Translator
.getNpcLogicActionActivate(herbivores
, context
, action
, rtHerbiGrp
)
799 local action3
= r2
.Translator
.getNpcLogicActionActivate(carnivores
, context
, action
, rtCarniGrp
)
800 local action4
= r2
.Translator
.createAction("user_event_trigger", rtNpcGrp
.Id
, 4)
801 local multiaction
= r2
.Translator
.createAction("multi_actions", {action1
, action2
, action3
, action4
})
802 return multiaction
, multiaction
805 return r2
.Translator
.getFeatureActivationLogicAction(rtNpcGrp
, action
)
808 component
.getLogicEvent
= function(this
, context
, event
)
809 assert( event
.Class
== "LogicEntityAction")
810 local component
= this
812 local rtNpcGrp
= r2
.Translator
.getRtGroup(context
, component
.InstanceId
)
815 return r2
.Translator
.getFeatureActivationLogicEvent(rtNpcGrp
, event
)
818 component
.getLogicCondition
= function(this
, context
, condition
)
819 assert( condition
.Class
== "ConditionStep")
820 local component
= r2
:getInstanceFromId(condition
.Entity
)
822 local rtNpcGrp
= r2
.Translator
.getRtGroup(context
, component
.InstanceId
)
825 return r2
.Translator
.getFeatureActivationCondition(condition
, rtNpcGrp
)
828 function component
:getLogicTranslations()
829 local logicTranslations
= {}
830 r2
.Translator
.addActivationToTranslations(logicTranslations
)
831 return logicTranslations
834 function component
:registerMenu(logicEntityMenu
)
835 local name
= i18n
.get("uiR2EdFaunaFeature")
836 logicEntityMenu
:addLine(ucstring(name
), "lua", "", "FaunaFeature")
839 r2
.Features
["FaunaFeature"] = feature