Scripts help pls part 3 - SOLVED

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
Drakkan
Posts: 1318
Joined: Mon Dec 31, 2012 12:25 am

Scripts help pls part 3 - SOLVED

Post by Drakkan »

Hi folks. Whoever will help with some scripting will be credited and also receive extra reward in my mod :)

1. script which will check all champ inventories for items called charm1, charm2, charm3 and charm4. If all are found, then destroy all and do something (hudprint "quest completed") - SOLVED by AdrTru
SpoilerShow

Code: Select all

function getPartyItems()
   local i,j,a,entity
   local tab = {}
   for i = 1,4 do
      local champion = party.party:getChampion(i)
      for j = 1,32 do
         local ent = champion:getItem(j)
         if ent ~= nil then
            ent = ent.go
            if tab[ent.name]==nil then tab[ent.name] = {} end
            table.insert(tab[ent.name],{ent.id,i,j,nil})
            if ent.containeritem ~= nil then
               local box = ent.containeritem
               for a = 1,box:getCapacity() do
                  local iitem = box:getItem(a)
                  if iitem  ~= nil then
                     if tab[iitem.go.name]==nil then tab[iitem.go.name] = {} end
                     table.insert(tab[iitem.go.name],{iitem.go.id,i,j,a})
                  end
               end
            end
         end
      end
   end
   return tab
end

function scRocks()
   local v,champ,box,ent
   local tab = getPartyItems()
   if tab.rock == nil then return false end
   for _,v in ipairs(tab.rock) do
      box = nil
      if math.random(100)<101 then
         champ = party.party:getChampion(v[2])
         ent = champ:getItem(v[3])
         if v[4] ~= nil then
            box = ent.go.containeritem
            ent = box:getItem(v[4])
         end
         if ent:getStackSize() == 1 then
            if v[4] == nil then champ:removeItemFromSlot(v[3]) else box:removeItemFromSlot(v[4]) end
         else ent:setStackSize(ent:getStackSize()-1) end
      end
   end
end

function scCharm()
   local charms = {"charm_1","charm_2","charm_3","charm_4"}
   local champ,box,ent
   local tab = getPartyItems()
   local ok = chooseItems(tab,charms,true)
   if ok == false then return false end
   for _,ch in ipairs(charms) do
      print(ch)
      for k,v in pairs(tab[ch]) do
         champ = party.party:getChampion(v[2])
         ent = champ:getItem(v[3])
         if v[4] ~= nil then
            box = ent.go.containeritem
            ent = box:getItem(v[4])
         end
         if v[4] == nil then champ:removeItemFromSlot(v[3]) else box:removeItemFromSlot(v[4]) end
      end
   end
   hudPrint("quest completed")
end

function chooseItems(tab,items,allOf)
   if type(items) == "string" then items = {items} end
   local ok = true
   local v
   for _,v in ipairs(items) do
      if tab[v] == nil then ok = false end
   end
   if (allOf and ok) or (allOf ~= true) then ok = true else ok = false end
   return ok
end
2. similar script, which will check all inventories for item "rock" (stackable). If found, then do random math 10% - if succeed, remove 1 rock from the stack. If not succeed, or no rock remaining, do nothing. - SOLVED by AdrTru

3. easy script, which will spawn object called "apple" on altar called "apple_altair" - SOLVED by Frenchie
SpoilerShow

Code: Select all

apple_altar.surface:addItem(spawn("apple").item)
4. It is somehow possible to limit object healing_crystal to be able heal for example only two times (that it will be not charged again) ? - SOLVED by AdrTru
SpoilerShow

Code: Select all

defineObject{
   name = "healing_crystal_2use",
   baseObject = "healing_crystal",
   components = {
        {
            class = "Counter",
         name = "counter",
         onActivate = function(self)
            self.go.clickable:disable()
            self.go.crystal:setCooldown(math.huge)
         end,
         onInit = function(self)
            self:setValue(2);
         end,
        },
      {
         class = "Clickable",
         offset = vec(0, 1.5, 0),
         size = vec(1.6, 2, 1.6),
         maxDistance = 1,
         onClick = function(self)
            if self.go.crystal:isEnabled() then self.go.counter:decrement() end
         end,
      },
   }
}
5. script which will move party one square forward - SOLVED by Frenchie
SpoilerShow
5) I can directly help you as I already made the script:

Code: Select all

    function Move(st)
    fa = party.facing
    le = party.level
    xx = party.x
    yy = party.y
    zz = party.elevation
    dx, dy = getForward(fa)
    party:setPosition(xx + dx * st, yy + dy * st, fa, zz, le)
    end
or another solution advised by minmay
SpoilerShow

Code: Select all

party.party:knockback(party.facing)
6. I have counter which will have different values during game play. What I need is script which will check if champion named "Drakkan" is in the party and then check for value of the counter. If value is for example 1 (and champion is in the party), then hudprint "something first...", if value of counter is 2 then hudpprint "something two" etc... if "drakkan" is not present or counter has some not defined value, do nothing.
so for example trigger will check - if champ drakkan is in party and value counter == 3 then hudprint... else do nothing

SOLVED by Frenchie
SpoilerShow

Code: Select all

message = { "something first", "something two" }
for i = 1,4 do if party.party:getChampion( i ):getName() == "Drakkan" and counter < 3 then hudprint ( message [ counter ] ) end end
thanks for any help
Last edited by Drakkan on Mon Feb 02, 2015 11:40 pm, edited 21 times in total.
Breath from the unpromising waters.
Eye of the Atlantis
User avatar
Frenchie
Posts: 219
Joined: Wed Oct 16, 2013 2:50 am

Re: Script help pls part 3

Post by Frenchie »

4) A healing crystal is a one time used object without charges, but you could spawn a stack of 2 by:

Code: Select all

spawn("crystal_shard_healing").item:setStackSize(2)
5) I can directly help you as I already made the script:

Code: Select all

function Move(st) 
fa = party.facing
le = party.level
xx = party.x
yy = party.y
zz = party.elevation
dx, dy = getForward(fa)
party:setPosition(xx + dx * st, yy + dy * st, fa, zz, le) 
end
st here is the number of steps to move and in your case Move(1). What is doesn't do is check for walls or mobs and you can get stuck
User avatar
Drakkan
Posts: 1318
Joined: Mon Dec 31, 2012 12:25 am

Re: Script help pls part 3

Post by Drakkan »

Frenchie wrote:[/code]
5) I can directly help you as I already made the script:

Code: Select all

function Move(st) 
fa = party.facing
le = party.level
xx = party.x
yy = party.y
zz = party.elevation
dx, dy = getForward(fa)
party:setPosition(xx + dx * st, yy + dy * st, fa, zz, le) 
end
st here is the number of steps to move and in your case Move(1). What is doesn't do is check for walls or mobs and you can get stuck
thanks for the code, this is sufficient for me. As for the healing crystal i know about the shards, But Id like to limit directly object healing_crystal (the big blue one) to be not re-charged after some use. I remember this was somehow hardcoded in Log1, not sure if it is different now.
Breath from the unpromising waters.
Eye of the Atlantis
User avatar
Frenchie
Posts: 219
Joined: Wed Oct 16, 2013 2:50 am

Re: Scripts help pls part 3

Post by Frenchie »

Ah, I misunderstood the healing crystal. Perhaps after checking it was used make a cave-in so it's no longer accessable?

edit: I had a connection problem, hence the weird sentence. What I wanted to say if the healing crystal breaks down after using it and after 2 uses it caves in or shatters...
Last edited by Frenchie on Tue Jan 27, 2015 5:17 am, edited 1 time in total.
User avatar
AdrTru
Posts: 223
Joined: Sat Jan 19, 2013 10:10 pm
Location: Trutnov, Czech Republic

Re: Scripts help pls part 3

Post by AdrTru »

I made little change on party search script and create table of items for 1/ and 2/ problem.
Connect scripts -> scRock() and scCharm()
Try this script:

Code: Select all

function getPartyItems()
	local i,j,a,entity
	local tab = {}
	for i = 1,4 do
		local champion = party.party:getChampion(i)
		for j = 1,32 do
			local ent = champion:getItem(j)
			if ent ~= nil then
				ent = ent.go
				if tab[ent.name]==nil then tab[ent.name] = {} end
				table.insert(tab[ent.name],{ent.id,i,j,nil})
				if ent.containeritem ~= nil then
					local box = ent.containeritem
					for a = 1,box:getCapacity() do
						local iitem = box:getItem(a)
						if iitem  ~= nil then
							if tab[iitem.go.name]==nil then tab[iitem.go.name] = {} end
							table.insert(tab[iitem.go.name],{iitem.go.id,i,j,a})
						end
					end
				end
			end
		end
	end
	return tab
end

function scRocks()
	local v,champ,box,ent
	local tab = getPartyItems()
	if tab.rock == nil then return false end
	for _,v in ipairs(tab.rock) do
		box = nil
		if math.random(100)<101 then
			champ = party.party:getChampion(v[2])
			ent = champ:getItem(v[3])
			if v[4] ~= nil then
				box = ent.go.containeritem
				ent = box:getItem(v[4])
			end
			if ent:getStackSize() == 1 then
				if v[4] == nil then champ:removeItemFromSlot(v[3]) else box:removeItemFromSlot(v[4]) end
			else ent:setStackSize(ent:getStackSize()-1) end
		end
	end
end

function scCharm()
	local charms = {"charm_1","charm_2","charm_3","charm_4"}
	local champ,box,ent
	local tab = getPartyItems()
	local ok = chooseItems(tab,charms,true)
	if ok == false then return false end
	for _,ch in ipairs(charms) do
		print(ch)
		for k,v in pairs(tab[ch]) do
			champ = party.party:getChampion(v[2])
			ent = champ:getItem(v[3])
			if v[4] ~= nil then
				box = ent.go.containeritem
				ent = box:getItem(v[4])
			end
			if v[4] == nil then champ:removeItemFromSlot(v[3]) else box:removeItemFromSlot(v[4]) end
		end
	end
	hudPrint("quest completed")
end

function chooseItems(tab,items,allOf)
	if type(items) == "string" then items = {items} end
	local ok = true
	local v
	for _,v in ipairs(items) do
		if tab[v] == nil then ok = false end
	end
	if (allOf and ok) or (allOf ~= true) then ok = true else ok = false end
	return ok
end

EDIT: bugfix of this script for Items inserted in containers
Last edited by AdrTru on Wed Jan 28, 2015 11:00 pm, edited 2 times in total.
My LOG2 projects: virtual money, Forge recipes, liquid potions and
MultiAlcoveManager, Toolbox, Graphic text,
minmay
Posts: 2790
Joined: Mon Sep 23, 2013 2:24 am

Re: Script help pls part 3

Post by minmay »

Frenchie wrote:4) A healing crystal is a one time used object without charges, but you could spawn a stack of 2 by:

Code: Select all

spawn("crystal_shard_healing").item:setStackSize(2)
5) I can directly help you as I already made the script:

Code: Select all

function Move(st) 
fa = party.facing
le = party.level
xx = party.x
yy = party.y
zz = party.elevation
dx, dy = getForward(fa)
party:setPosition(xx + dx * st, yy + dy * st, fa, zz, le) 
end
st here is the number of steps to move and in your case Move(1). What is doesn't do is check for walls or mobs and you can get stuck
A much better way to do this is to use the PartyComponent:knockback() function:

Code: Select all

party.party:knockback(party.facing)
Knockback will check for walls/obstacles/etc and prevent them from getting stuck, and it moves them smoothly (albeit more quickly than they would normally move). The setPosition method is bad for about 50 different reasons that I'm mostly not interested in enumerating.
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
Frenchie
Posts: 219
Joined: Wed Oct 16, 2013 2:50 am

Re: Scripts help pls part 3

Post by Frenchie »

The knockback works a lot better than my script, but I used it for more than 1 step and also to bridge obstacles.

The below suggestions are just ideas that might not work:

3) Apple altar :

Code: Select all

apple_altar.surface:addItem(spawn("apple").item)
6) Counter / party member :

Code: Select all

message = { "something first", "something two" }
for i = 1,4 do if party.party:getChampion( i ):getName() == "Drakkan" and counter < 3 then hudprint ( message [ counter ] ) end end
User avatar
Eleven Warrior
Posts: 752
Joined: Thu Apr 18, 2013 2:32 pm
Location: Australia

Re: Scripts help pls part 3

Post by Eleven Warrior »

Hi. With the (st) do I type in a number for the party to move forward eg: 1 or 2 or 3 etc...? Thxs :)
User avatar
Drakkan
Posts: 1318
Joined: Mon Dec 31, 2012 12:25 am

Re: Scripts help pls part 3

Post by Drakkan »

thanks for help guys, I tried and everything is working just fine. You will receive special thanks when mod is released and you will be credited as well.
Breath from the unpromising waters.
Eye of the Atlantis
User avatar
AdrTru
Posts: 223
Joined: Sat Jan 19, 2013 10:10 pm
Location: Trutnov, Czech Republic

Re: Scripts help pls part 3 - SOLVED

Post by AdrTru »

I am sorry, my script for 1/ and 2/ had bug in items in containers.
script is fixed.

about 4/. I try to make new healing_crystal like this (I think that its working correctly):

Code: Select all

defineObject{
	name = "healing_crystal_2use",
   baseObject = "healing_crystal",
   components = {
        {
            class = "Counter",
			name = "counter",
			onActivate = function(self)
				self.go.clickable:disable()
				self.go.crystal:setCooldown(math.huge)
			end,
			onInit = function(self)
				self:setValue(2);
			end,
        },
		{
			class = "Clickable",
			offset = vec(0, 1.5, 0),
			size = vec(1.6, 2, 1.6),
			maxDistance = 1,
			onClick = function(self)
				if self.go.crystal:isEnabled() then self.go.counter:decrement() end
			end,
		},
	}
}
My LOG2 projects: virtual money, Forge recipes, liquid potions and
MultiAlcoveManager, Toolbox, Graphic text,
Post Reply