Ask a simple question, get a simple answer

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

Whatever object is being called from line 13542, is missing its tiledamager component, or the component has a custom name.

Post the section of log2_monsters.lua surrounding line 13542.
minmay
Posts: 2768
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay »

You need to add a component named "tiledamager" to your shock_wave object. This is because BlastComponent does

Code: Select all

self.go.tiledamager:disable()
on initialization if it's not on the floor or a platform (like IceShardsComponent).

This should fix it:

Code: Select all

defineObject{
	name = "shock_wave",
	baseObject = "base_spell",
	components = {
		{
			class = "Blast",
			delay = 0.2,
			effect = "shockburst",
		},
		-- hack to prevent BlastComponent error
		{
			class = "Null",
			name = "tiledamager",
			enabled = false,
		},
	}
}
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

8-) That's a neat trick.
User avatar
Lorial
Posts: 91
Joined: Sat Dec 29, 2018 12:27 pm

Re: Ask a simple question, get a simple answer

Post by Lorial »

Solved
Last edited by Lorial on Wed Jun 23, 2021 11:37 am, edited 4 times in total.
bongobeat
Posts: 1076
Joined: Thu May 16, 2013 5:58 pm
Location: France

Re: Ask a simple question, get a simple answer

Post by bongobeat »

thanks for your help! 8-)
My asset pack: viewtopic.php?f=22&t=9320

Log1 mod : Toorum Manor: viewtopic.php?f=14&t=5505
User avatar
Lorial
Posts: 91
Joined: Sat Dec 29, 2018 12:27 pm

Re: Ask a simple question, get a simple answer

Post by Lorial »

Need some help with the surfaces for my custom alcove below.

Both alcoves have their own surface and both areas are clickable, can be filled with items via editor and emptied manually. However, as soon as I insert an item it only uses surface_1, the upper alcove.
Am I overseeing something or is that simply not possible and requires me to cheat with an invisible pedestal? Not sure if that works either...
Also, is naming the alcoves individually even necessary?

Code: Select all

defineObject{
	name = "catacomb_alcove_empty_low",
	baseObject = "base_wall",
	components = {
		{
			class = "Model",
			model = "mod_assets/models/catacomb_alcove_empty_low.fbx",
			staticShadow = true,
		},
		{
			class = "Occluder",
			model = "assets/models/env/catacomb_alcove_01_occluder.fbx",
		},
		{
			class = "Surface",
			name = "surface_1",
			offset = vec(0, 1.37, 0.2),
			size = vec(2.2, 0.65),
		},
		{
			class = "Clickable",
			name = "clickable1",
			offset = vec(0, 1.32+0.1, 0),
			size = vec(1.1, 0.2, 0.9),
			pedestal = true,
		},

		{
			class = "Surface",
			name = "surface_2",
			offset = vec(0, 0.35, 0),
			size = vec(2, 0.35),
		},
		{
			class = "Clickable",
			name = "clickable2",
			offset = vec(0, 0.5+0.1, 0),
			size = vec(1.1, 0.2, 0.9),
			pedestal = true,
		},
	},
	editorIcon = 92,
	minimalSaveState = false,
}
minmay
Posts: 2768
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay »

The game picks the first accepting SurfaceComponent on the object when you click a ClickableComponent; it has no way of knowing that you want clickable2 to correspond to surface_2. To work around this, you can use the onAcceptItem hook to reject the item from all SurfaceComponents except the one you want the item to go to. So you'd want something like this:

Code: Select all

		{
			class = "Surface",
			name = "surface_1",
			offset = vec(0, 1.37, 0.2),
			size = vec(2.2, 0.65),
			onAcceptItem = function(self,item)
				local surf = GameMode.tempSurface
				GameMode.tempSurface = nil
				if surf ~= 1 then return false end
			end,
		},
		{
			class = "Clickable",
			name = "clickable1",
			offset = vec(0, 1.32+0.1, 0),
			size = vec(1.1, 0.2, 0.9),
			pedestal = true,
			onClick = function(self)
				if getMouseItem() then GameMode.tempSurface = 1 end
			end,
		},
		{
			class = "Surface",
			name = "surface_2",
			offset = vec(0, 0.35, 0),
			size = vec(2, 0.35),
			onAcceptItem = function(self,item)
				local surf = GameMode.tempSurface
				GameMode.tempSurface = nil
				if surf ~= 2 then return false end
			end,
		},
		{
			class = "Clickable",
			name = "clickable2",
			offset = vec(0, 0.5+0.1, 0),
			size = vec(1.1, 0.2, 0.9),
			pedestal = true,
			onClick = function(self)
				if getMouseItem() then GameMode.tempSurface = 2 end
			end,
		},
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
User avatar
Lorial
Posts: 91
Joined: Sat Dec 29, 2018 12:27 pm

Re: Ask a simple question, get a simple answer

Post by Lorial »

minmay wrote: Wed Jun 23, 2021 7:54 pm The game picks the first accepting SurfaceComponent on the object when you click a ClickableComponent; it has no way of knowing that you want clickable2 to correspond to surface_2. To work around this, you can use the onAcceptItem hook to reject the item from all SurfaceComponents except the one you want the item to go to. So you'd want something like this:
Unfortunately, I could not get it to work as intended, but thank you for your effort anyway.
Found a different workaround with slim pedestals like steps in front of a wall, so with the upper alcove working, there are now 4 properly clickable ones in line.

Question regarding spell icons.
I am trying to use my own atlas files in the spell definition for spellIcon (rune panel) and icon (trait panel). However, I keep receiving an error message of an asset processor that cannot be found for the file in ["string "Spells.lua"]. Whatever that means.

The spell icon atlas in the asset pack was not a multitude of 50x50, so I fixed that, but still no luck. Tried using a single 50x50 one or 75x75 (for the icon) and the result is the same. This method works for items, why not for spells?
SpoilerShow

Code: Select all

defineSpell{ 
	[...]
--	spellIcon = 1,
	spellIcon = 0,
	spellIconAtlas = "mod_assets/textures/spell_icon",

	icon = 3,
--	iconAtlas = "mod_assets/textures/spell_icons",
}
Error message (image won't show, how ironic):
User avatar
Isaac
Posts: 3172
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

Your spell_icon files each need a .dds extension (on the drive), and .tga extensions in the script.

Code: Select all

spellIconAtlas = "mod_assets/textures/spell_icon.tga",
User avatar
Lorial
Posts: 91
Joined: Sat Dec 29, 2018 12:27 pm

Re: Ask a simple question, get a simple answer

Post by Lorial »

Ah, this works, thanks. So it has to be tga specifically in order to recognize the file, weird.

1) Teleporter/Spin:
The teleporter below is supposed to spawn briefly and turn incoming projectiles and monsters around on the same tile, but it doesn't. If I give it a specific TeleportTarget it works, unless starting location and target are identical, even disregarding different elevation.
Besides is there a way to use the current getPosition as a target location? Getting an error that it has to be a number.
SpoilerShow

Code: Select all

defineObject{
	name = "teleport_spin",
	components = {
		{
			class = "Teleporter",
			triggeredByParty = true,
			triggeredByMonster = true,
			triggeredByItem = true,
			spin = "north",
			--spin = "turn_around",
			--onInit = function(self)
			--	self.go.teleporter:setTeleportTarget(1,0,1,0)
			--end,
		},
		{
			class = "Controller",
			initialState = "activate",

			onInitialActivate = function(self)
				self.go.teleporter:enable()
				self.go.timer:start()
			end,
			onInitialDeactivate = function(self)
				self.go.teleporter:disable()
			end,
			onActivate = function(self)
				self.go.teleporter:enable()
				self.go.light:fadeIn(0.5)
			end,
			onDeactivate = function(self)
				self.go.teleporter:disable()
			end,
			onToggle = function(self)
				if self.go.teleporter:isEnabled() then
					self:deactivate()
				else
					self:activate()
				end
			end,
		},
		{
			class = "Timer",
			currentLevelOnly = false,
			triggerOnStart = false,
			disableSelf = true,
			timerInterval = 1,

			onActivate = function(self)
				self.go:destroyDelayed()
			end,
		},
	},
}
Traits:
2) I am trying to include 3 item slots in a trait. It does work if only two are active at a time, adding all 3 items won't work. Does this even work with more than 2 slots?
The cloak and dagger should only affect the hand with the dagger, but it effects both hands. Is there a way to limit a bonus to one hand/slot only?
SpoilerShow

Code: Select all

defineTrait{
	name = "rogue_accuracy",
	uiName = "Rogue Accuracy",
	icon = 34,
	hidden = true,
	description = ".",
	onComputeAccuracy = function(champion, weapon, attack, attackType, level)
		if level > 0 then 
			local item1 = champion:getItem(ItemSlot.Weapon)
			local item2 = champion:getItem(ItemSlot.OffHand)
			local item3 = champion:getItem(ItemSlot.Cloak)		
		if (item2 and item2:hasTrait("dagger")) and (item1 and item1:hasTrait("dagger")) then return math.floor(champion:getLevel()/2)
		end
		if (item3 and item3:hasTrait("cloak")) and (item1 and item1:hasTrait("dagger")) then return math.floor(champion:getLevel()*3/4)
		end
		if (item3 and item3:hasTrait("cloak")) and (item2 and item2:hasTrait("dagger")) then return math.floor(champion:getLevel()*3/4)
		end
		if  (item1 and item1:hasTrait("dagger")) and (item2 and item2:hasTrait("dagger")) and (item3 and item3:hasTrait("cloak")) then return math.floor(champion:getLevel()*3/4)
		end
		end
	end,
}
3) Is there a way to use recomputeCooldown for casting spells? The radiant orb has the line "special: Faster Spell Casting", but unfortunately it does speed up nothing (tested wands vs orb). Using specific item slots with item.go.runepanel only affects the weapon, but not the spellcasting.
SpoilerShow

Code: Select all

defineTrait{
	name = "cooldown_caster",
	uiName = "Caster cooldown",
	icon = 34,
	description = "Reduces Cooldown when casting spells.",
	onComputeCooldown = function(champion, weapon, attack, attackType, level)
		if level > 0 then 
			local item1 = champion:getItem(ItemSlot.Weapon)
			local item2 = champion:getItem(ItemSlot.OffHand)	
		if (item2 and item2.go.runepanel) and (item1 and item1:hasTrait("staff")) then return 0.7
		end
		if (item1 and item1.go.runepanel) and (item2 and item2:hasTrait("staff")) then return 0.7
		end
		end
	end,
}
Magic, people:
4) How can the spell costs be altered, depending on the casters magic school proficiency or willpower stat?
How about casting a stronger version like lightning bolt which becomes a greater one (wasn't that in the base game)? Apparently, using two versions with the same gesture twice is a no-go and only the higher level is cast, the lower one disabled till then.

5) When defining a custom spell and setting a condition or spawning something, the added skilllevel doesn't seem to have any effect on length or damage. What does it actually do?
SpoilerShow

Code: Select all

   onCast = function(champion, x, y, direction, elevation, skillLevel)
      playSound("generic_spell")
      for i = 1, 4, 1 do
         if party.party:getChampion(i):isAlive() then
            party.party:getChampion(i):setCondition("feather", skillLevel*2)
         end
	 end
   end,
Post Reply