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!
AdrianKnight
Posts: 21
Joined: Wed Aug 30, 2017 9:21 pm

Re: Ask a simple question, get a simple answer

Post by AdrianKnight »

I would like to forbid resting if there are monsters in the 80 tiles surrounding the party (considering a 9x9 square with the party at the center of it).

Code: Select all


defineObject{
name = "party",

baseObject = "party",
components = {
{
			class = "Party",

			onRest = function(self)

			-- if there are monsters in the 80 tiles surrounding the party then

				for i = 1 , 4 do
 				local name = party.party:getChampion(i):getName()
				 if party.party:getChampion(i):isAlive() == true then
				   playSound("polymorph_bear")
				   hudPrint(name .. " says: 'We can't rest here. There are monsters in the surroundings.'")
				   break
				 end
				end

				return false

			-- end

			end,
},
},
}

How could I check if there are monsters in the 80 tiles surrounding the party ?

Thank you for your help.
minmay
Posts: 2768
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay »

For such a large number of tiles, allEntities() will usually be faster than entitiesAt():

Code: Select all

onRest = function(self)
	local go = self.go
	local px = go.x
	local py = go.y
	local abs = math.abs
	local max = math.max
	for e in go.map:allEntities() do
		if e.monster and e.monster:isAlive() and max(abs(e.x-px), abs(e.y-py)) <= 4 then
			for i = 1 , 4 do
				if self:getChampion(i):isAlive() then
					playSound("polymorph_bear")
					local name = self:getChampion(i):getName()
					hudPrint(name .. " says: 'We can't rest here. There are monsters in the surroundings.'")
					return false
				end
			end
		end
	end
end
untested so i probably made a typo somewhere

Warning: If your dungeon has a DiggingToolComponent (like a shovel) or RopeToolComponent (like a rope) anywhere in it, and you ever return false from the onRest hook, you must also write code to prevent the DiggingToolComponent or RopeToolComponent from being used when the onRest hook will return false. Otherwise, you will break people's saved games. See mod_assets/core/scripts/reduced_standard_assets/items/misc.lua in ORRR3's source code.

Also, you asked for (and I provided) a Chebyshev distance test, but Grimrock uses Taxicab geometry for party and monster movement, not Chebyshev. So it would make more sense to use a Taxicab distance check: abs(e.x-px)+abs(e.y-py) <= [distance] instead of max(abs(e.x-px), abs(e.y-py)) <= [distance]. Consider this.
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.
AdrianKnight
Posts: 21
Joined: Wed Aug 30, 2017 9:21 pm

Re: Ask a simple question, get a simple answer

Post by AdrianKnight »

Thank you.

I have another question to ask.
I noticed that the poison_cloud_medium spawned by the poison_bolt_greater_blast does not grant experience to the party when it kills a monster, even when the poison_bolt_greater is cast by a champion.

Code: Select all


defineObject{
	name = "poison_bolt_greater",
	baseObject = "poison_bolt",
	components = {
		{
			class = "Projectile",
			spawnOffsetY = 1.35,
			velocity = 10,
			radius = 0.1,
			hitEffect = "poison_bolt_greater_blast",
		},
	},
}

defineObject{
	name = "poison_bolt_greater_blast",
	baseObject = "poison_bolt_blast",
	components = {
		{
			class = "TileDamager",
			attackPower = 35,
			damageType = "poison",
			sound = "poison_bolt_hit",
			screenEffect = "poison_bolt_screen",
			onInit = function(self)
				local cloudspell = self.go:spawn("poison_cloud_medium").cloudspell
				local ord = self:getCastByChampion()
				if cloudspell and ord then
					cloudspell:setCastByChampion(ord)
				end
			end,
			onHitMonster = function(self, monster)
				monster:setCondition("poisoned", 25)

				-- mark condition so that exp is awarded if monster is killed by the condition
				local poisonedCondition = monster.go.poisoned
				local ord = self:getCastByChampion()
				if poisonedCondition and ord then
					poisonedCondition:setCausedByChampion(ord)
				end
			end,
		},
	},
}

Why ?
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 »

Hey there and merry Christmas


I think I've already asked about that, but did someone manage to change the color of the name of items?

Like having the epic items name in yellow, and other specific item's name in another color.
My asset pack: viewtopic.php?f=22&t=9320

Log1 mod : Toorum Manor: viewtopic.php?f=14&t=5505
Kirill
Posts: 125
Joined: Mon Dec 21, 2020 5:36 pm

Re: Ask a simple question, get a simple answer

Post by Kirill »

bongobeat wrote: Sun Dec 25, 2022 6:14 pm Hey there and merry Christmas


I think I've already asked about that, but did someone manage to change the color of the name of items?

Like having the epic items name in yellow, and other specific item's name in another color.

New mod by Adragedron "Final Adventure" have this. Epic items have name in gold.


p.s. When you plan to release your LoG2 mod? Do you need testers?
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 »

Is there a console command line for disabling the lockParty from GRIMTK?

(other than GameMode.setGameFlag("DisableMovement", false); GameMode.setGameFlag("DisableMouseLook", false); )

If you got 2 dialogues at the same time, it blocks definetely the party at the end of the dialogue.

The previous commands works to unlock the party, but if you get another dialogue, you get blocked again at the end of the dialogue.

I'm asking because a player get blocked after "returning" a quest, and the only reason I thought about that issue is that he got 2 dialogues at the same time, I've already experienced that, but in that case, its a little odd, as you can't have those 2 dialogues at the same time, exept if you teleport yourself and do the job (before getting the quest), then come back to "return" the quest.
My asset pack: viewtopic.php?f=22&t=9320

Log1 mod : Toorum Manor: viewtopic.php?f=14&t=5505
minmay
Posts: 2768
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay »

The preferred solution here would be to organize your dialogue system better, because GrimTK is not designed to support having multiple dialogues simultaneously, and this isn't the only problem you'll have if you try to do it anyway.

But if you really do need to just unlock the party, use GTK.Core.GUI:unlockParty() until GTK.Core.GUI:isPartyLocked() returns false, call GTK.Core.GUI:unlockKeyboard() until GTK.Core.GUI:isKeyboardLocked() returns false, and call GTK.Core.GUI:unfreezeAI() until GTK.Core.GUI:isAIFrozen() returns 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.
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 »

Ok thank you, will try that.

Well, hopefully I do not use 2 dialogues at the same time (I wonder who will).
To have that issue, I figured the player has done a thing before another and get stuck then. (It can't happen, but if you use the console to teleport the party, well, the mess came).
My asset pack: viewtopic.php?f=22&t=9320

Log1 mod : Toorum Manor: viewtopic.php?f=14&t=5505
2498billb
Posts: 40
Joined: Thu Dec 30, 2021 6:06 pm

Re: Ask a simple question, get a simple answer

Post by 2498billb »

Hi all
I am trying to create a mine access certificate using the letter item, to place in an alcove to open a mine door, but using the following code in a script it will not work:

Code: Select all

function surfaceContains(surface, item)
	for v,i in surface:contents() do
		if i.go.name == item then
			return true
		end
	end
	return false
end

function mineaccess() 
	if surfaceContains(mine_alcove_1.surface, "mine_access_certificate") then
		mine_door_1.door:open()
	else
		mine_door_1.door:close()
	end
end

-- mine_access_certificate
defineObject{
	name = "mine_access_certificate",  
	baseObject = "base_item",
	components = {
		{
			class = "Model",
			model = "assets/models/items/waxseal_note.fbx",
		},
		{
			class = "Item",
			uiName = "Mine Access Certificate",
			gfxIndex = 235,
			weight = 0.1,
		},
		{
			class = "ScrollItem",
			textAlignment = "left",
		},
	},
}
I have tried the same code using a 'pickaxe' for the alcove item and this is ok
I know the Guardians mod had a similar set up to access the mine, what am i doing wrong
in the script? any help welcome thx in advance.
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 »

The problem is that defineObject{} cannot be in a user script. It is normally placed in the objects.lua file in the mod's scripts folder.
It must be loaded when the game starts, to be able to create the mine_access_certificate object—before it can be called or tested.

This is the only thing preventing your current script from working.
___________

There are a few other ways to do this. An easier way is just to have the alcove only accept the mine certificate item; opening the door when it's offered. This also requires defining the asset in the object.lua script file.
SpoilerShow

Code: Select all

-- mine_certificate_alcove
defineObject{
	name = "mine_certificate_alcove",
	baseObject = "mine_alcove",
	components = {
		{
			class = "Surface",
			offset = vec(0, 0.85, -0.75),
			size = vec(1.5, 0.65),

			onAcceptItem = function(self, item) 
							local accept = item.go.name == "mine_access_certificate"
							---[[ audio/visual effects
								if not accept then playSound("lock_incorrect") 
									party.party:shakeCamera(0.05,0.02)	
								end
							--]]
							return accept
						end,
		},
	},
}

-- mine_access_certificate
defineObject{
	name = "mine_access_certificate",  
	baseObject = "letter",
	components = {
		},
}
Connect the alcove to the door. The alcove will only open the door when it accepts the certificate.
Here is an alternative option that does work from a user script; no need to define custom objects:
SpoilerShow
For this one you must connect the alcove to the script object for it to work.

Code: Select all

--Quick mine certificate item for this example.
do
		local certId = findEntity(self.go:spawn("note").id)
		  certId.item:setUiName("Mine Access Certificate")
		  certId.item:setGameEffect("Grants access to the Mine Door")
		  certId.item:setGfxIndex(235)
		  certId.model:setModel("assets/models/items/waxseal_note.fbx")
		
		 -- Optional repositioning of the certificate item; otherwise it appears on the ground where you place this script_entity.
		 --    certId:setPosition(15,15,0,0,1)
end	
--::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::--

function _checkForItem(surface,itemName)
	for _,each in surface:contents() do
		if each.go.item:getUiName() == itemName then
			return true
		end
	end	
end

function openGate(gate)
	if _checkForItem(gate,"Mine Access Certificate") then mine_door_1.door:open() end
end
Post Reply