Page 4 of 5

Re: Modding infodump

Posted: Sun Oct 23, 2016 5:37 am
by minmay
Sorry, I haven't been looking into it.

Re: Modding infodump

Posted: Sun Oct 23, 2016 8:17 am
by akroma222
Not a problem!
A further question... Anyone with any hints appreciated :)

If I needed to find which of the 2 Champs was to be hit by a (spell-based) custom Projectile (which hit the Party on a given Side)....
...what would/should I be checking for ?? (Evasion plays no part in projectiles hitting Champs - as stated above)
... DEX ? traits? race? other conditions?? surely diff in Evasion would count?

Re: Modding infodump

Posted: Sun Oct 23, 2016 9:45 am
by minmay
When the party is hit by a projectile, both champions on the side of the projectile have an equal chance to be hit. It's the same for getting attacked by monsters that aren't part of groups.

Re: Modding infodump

Posted: Sun Oct 23, 2016 12:22 pm
by akroma222
Ahh well that's not too complex at all!
Thanks again 8-)

Re: Modding infodump

Posted: Thu Dec 08, 2016 6:52 am
by Lark
minmay wrote: Detecting reloads
To detect when the dungeon is loaded, place a single instance of this object anywhere in your dungeon:

Code: Select all

defineObject{
	name = "load_detector",
	placement = "floor",
	components = {
		{
			class = "Null",
			onInit = function(self)
				-- Whenever this function is called, the dungeon has
				-- been loaded; either a new game was started, or a
				-- saved game was loaded.
			end,
		},
	},
	editorIcon = 148,
	minimalSaveState = true,
}
]
Minmay: Thank you for the information. I understand the above and I'm wanting to build on it. Generically, what other conditions can be defined and how are they triggered? (Other conditions I've found are: onInitialActivate - appears to be run just once and NOT when the game is reloaded, onInitialDeactivate - I assume it runs only the first time it's deactivated, OnActivate, onDeactivate, and onToggle where I assume the last three are hit by scripts only.)

Specifically, I'm trying to define a floor tile that spawns a floor_trigger that calls a script contained in the object itself when the party steps on the tile. Spawning the trigger is no big deal, but can you connect the trigger to a script internal to the object? I can make it work with scripts external to the object, but it would be cleaner for the dungeon creator this way, I think. I also tried adding a script component but failed to get it to work.

I'd like something like myObj.floortrigger:addConnector("onActivate", self.go.id, "onDeactivate") but none of the combinations I've tried work.

Here's a test object:

Code: Select all

defineObject{
	name = "test_platform",
	baseObject = "base_floor_decoration",
	components = {
		{
			class = "Model",
      			model = "mod_assets/models/test_platform_01.fbx",
      			offset = vec(0,-3,-1.5),
			staticShadow = true,
		},
		{
			class = "Platform",
		},
		{
			class = "Controller",
			onInitialActivate = function(self)
				self:activate()
				local t = spawn("floor_trigger", self.go.level, self.go.x , self.go.y, self.go.facing, self.go.elevation, self.go.id .. "_trigger")
				t.floortrigger:setTriggeredByParty(true)
				t.floortrigger:setTriggeredByMonster(false)
				t.floortrigger:setTriggeredByItem(false)
				t.floortrigger:setTriggeredByDigging(false)
				t.floortrigger:setDisableSelf(false)
				t.floortrigger:addConnector("onActivate", self.go.id, "onDeactivate")	--This line fails... is it even possible?
			end,
			onInit = function(self)
				self.go.platform:enable()
			end,
			onInitialDeactivate = function(self)
				self.go.platform:disable()
			end,
			onActivate = function(self)
				print(self.go.id .. " onActivate raised.")
			end,
			onDeactivate = function(self)
				self.go.platform:disable()
				print(self.go.id .. " onDeactivate raised.")
			end,
			onToggle = function(self)
				if self.go.platform:isEnabled() then
					self:deactivate()
				else
					self:activate()
				end
			end,
		},		

	},
	minimalSaveState = true,
}
Has anyone done this? Thank you all for your time! -Lark

Re: Modding infodump

Posted: Thu Dec 08, 2016 8:15 am
by zimberzimber
You can call an internal function (from a script component) from any other function (onInit, onActivate, onAnimationEvent, etc...) by having it 'navigate' to the script component, and execute a script as you would normally trigger functions through scripts.

Here's a definition of an Omnitool I made, which is basically a timer merged with a script entity, which can also be disabled by external sources.

Code: Select all

defineObject{
	name = "omnitool",
	components = {
		{
			class = "Timer",
			timerInterval = 120,
			onActivate = function(self)
				self.go.script:omnitoolFunction(self)
			end,
		},
		{
			class = "Controller",
			onActivate = function(self)
				self.go.timer:enable()
			end,
			onDeactivate = function(self)
				self.go.timer:disable()
			end,
			onToggle = function(self)
				if self.go.timer:isEnabled() then
					self.go.timer:disable()
				else
					self.go.timer:enable()
				end
			end,
		},
		{
			class = "Script",
			source = [[
function omnitoolFunction(self)
	hudPrint("Omnitool labled '"..self.go.id.."' activated at ("..self.go.x..","..self.go.y..")")
end
]]
		},
	},
	placement = "floor",
	editorIcon = 268,
	tags = { "zim_assets" },
}
As you can see, every time the timer runs out, it'll call the omnitoolFunction(). The script can be then edited in-editor, just like a script entity.
If you don't have a large screen, you'll probably not see the input box on the object, so you'll have to shrink the in-game view box. The input box appears at the bottom, after the full component list.

Re: Modding infodump

Posted: Thu Dec 08, 2016 10:17 am
by minmay
Lark wrote:Minmay: Thank you for the information. I understand the above and I'm wanting to build on it. Generically, what other conditions can be defined and how are they triggered? (Other conditions I've found are: onInitialActivate - appears to be run just once and NOT when the game is reloaded, onInitialDeactivate - I assume it runs only the first time it's deactivated, OnActivate, onDeactivate, and onToggle where I assume the last three are hit by scripts only.)
I think you're confused about the purpose of ControllerComponent. The ControllerComponent hooks have no inherent meaning. ControllerComponent exists so that you have a convenient, consistent way to handle connector messages, and has absolutely nothing to do with the passage you quoted. onActivate is only called when you call ControllerComponent:activate(), either from a script or by triggering a connector with the message "activate". onDeactivate is only called when you call ControllerComponent:deactivate(). onToggle is only called when you call ControllerComponent:toggle(), and so on.
onInitialActivate is called once, when the ControllerComponent initializes, if the initial state (as selected in the object inspector) is "activate". onInitialDeactivate is called once, when the ControllerComponent initializes, if the initial state (as selected in the object inspector) is "deactivate".

Aside from ControllerComponent:setInitialState(), none of the ControllerComponent methods do anything except call the hooks. If you call ControllerComponent:open(), and don't have an onOpen hook defined for that ControllerComponent, nothing whatsoever will happen.

The reason your object doesn't work is that you're passing the message "onDeactivate" when you wanted to pass the message "deactivate". I question the use of two objects here in the first place, however. Wouldn't this be easier?

Code: Select all

defineObject{
   name = "test_platform",
   baseObject = "base_floor_decoration",
   components = {
      {
         class = "Model",
               model = "mod_assets/models/test_platform_01.fbx",
               offset = vec(0,-3,-1.5),
         staticShadow = true,
      },
      {
         class = "Platform",
      },
      {
         class = "FloorTrigger",
         triggeredByMonster = false,
         triggeredByItem = false,
         triggeredByDigging = false,
         onActivate = function(self)
           self.go.controller:activate()
         end,
      },
      {
         class = "Controller",
         onInitialActivate = function(self)
            self:activate()
         end,
         onInitialDeactivate = function(self)
            self.go.platform:disable()
         end,
         onActivate = function(self)
            print(self.go.id .. " onActivate raised.")
         end,
         onDeactivate = function(self)
            self.go.platform:disable()
            print(self.go.id .. " onDeactivate raised.")
         end,
         onToggle = function(self)
            if self.go.platform:isEnabled() then
               self:deactivate()
            else
               self:activate()
            end
         end,
      },      
   },
}
(I assume that you putting minimalSaveState on this was an accident, since I can't imagine why you'd want to reactivate the platform and spawn an additional floor trigger every time the game is loaded...)

Re: Modding infodump

Posted: Thu Dec 08, 2016 6:22 pm
by Lark
Zimberzimber: Thank you! I'm just now seeing how you can combine different properties in the same object - like your script internal to your omnitool object. That really helps.

Minmay: Yes of course I see what you did in your example now and yes, it's much easier and proficuous. So duuuh :?, I never thought to combine classes that way, but now that I see it, it's beyond obvious. I get it now. Thank you!

Sincerely, -Lark

Re: Modding infodump

Posted: Sat Dec 10, 2016 10:04 pm
by Lark
zimberzimber wrote:You can call an internal function (from a script component) from any other function (onInit, onActivate, onAnimationEvent, etc...) by having it 'navigate' to the script component, and execute a script as you would normally trigger functions through scripts.
Zimber: I'm making progress and I have the internal script working because of your example, but I've found that when I change the script, I must delete and add the objects again - the old objects don't get the script change even on reloading the project. Can these scripts be external?

Code: Select all

      {
	     class = "Script",
	     setSource = "External",
	     loadFile = "mod_assets/scripts/test07.lua",
      },
The Scripting Reference shows that Script Components have the setSource and loadFile properties (although only loadFile appears to be required for external scripts), but everything I've tried in an object definition fails with something similar to "warning! invalid component property script.setSource". Have I missed something obvious again or is this not possible? I can't find any examples anywhere of someone defining an object with a script component that points to an external script.

Thanks, -Lark

Re: Modding infodump

Posted: Sat Dec 10, 2016 10:25 pm
by zimberzimber
1) The is no 'setSource' value in script, setSource and getSource are the functions that set/get the written script
2) 'source' is the written script, what the script typing box has in it when the object is created. Similar to what you'd type in a script_entity, except it begins with it. so setSource(string) is the equivalent of writing in a script entity inside an object.
3) You don't need 'source' and 'loadFile', because (from what I know), the latter will override the other.

EDIT: By the way, you don't have to link the object to an external through its definition, you can just give it a script component with written script (or without), and then link it through the editor. But always make sure the function called in the controller component exists in the internal/external script :!: