Script - Return Weapon to Alter

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
Xanathar
Posts: 629
Joined: Sun Apr 15, 2012 10:19 am
Location: Torino, Italy
Contact:

Re: Script - Return Weapon to Alter

Post by Xanathar »

x = party:getChampion(champ):getItem(slot)

should be

local x = party:getChampion(champ):getItem(slot)

otherwise x would be kept as a variable to save, and saving complex objects (like items) that way is not supported in save games.
Waking Violet (Steam, PS4, PSVita, Switch) : http://www.wakingviolet.com

The Sunset Gate [MOD]: viewtopic.php?f=14&t=5563

My preciousss: http://www.moonsharp.org
User avatar
undeaddemon
Posts: 157
Joined: Fri Mar 02, 2012 3:38 pm

Re: Script - Return Weapon to Altar

Post by undeaddemon »

Thanks! I will test that script adjustment in a bit.
:D
User avatar
undeaddemon
Posts: 157
Joined: Fri Mar 02, 2012 3:38 pm

Re: Script - Return Weapon to Alter

Post by undeaddemon »

OK, so I was thinking I might need to update the other scripts I have as well - but seems to create a problem:

Image

Code: Select all

function itemCheck(item)
   for champ = 1,4 do
   for slot = 7,8 do
      local x = party:getChampion(champ):getItem(slot)
      if x ~= nil then
      if x.name == item then
         party:getChampion(champ):removeItem(slot)
         returnItem(item,champ)
      end
      end   
   end   
   end   
end

function returnItem(item,champ)
   for slot = 11,32 do
         if slot < 32 then
            if party:getChampion(champ):getItem(slot) == nil then
               party:getChampion(champ):insertItem(slot,x)
               hudPrint("The Blade of Lightning becomes too painful to hold,")
			   hudPrint("and so is put into "..party:getChampion(champ):getName().."'s bag.")              
			break
            end
         else
            spawn(item,party.level,party.x,party.y,party.facing)
            hudPrint("The Blade of Lightning becomes too painful to hold,")
            hudPrint("and drops to the floor")
            break
         end
   end
end

function checkBlade()
   itemCheck("BladeOfLightning")
end
User avatar
Xanathar
Posts: 629
Joined: Sun Apr 15, 2012 10:19 am
Location: Torino, Italy
Contact:

Re: Script - Return Weapon to Alter

Post by Xanathar »

Change every instance of returnItem(item,champ) in returnItem(item,champ,x) as x is not globally visible anymore.
Waking Violet (Steam, PS4, PSVita, Switch) : http://www.wakingviolet.com

The Sunset Gate [MOD]: viewtopic.php?f=14&t=5563

My preciousss: http://www.moonsharp.org
User avatar
undeaddemon
Posts: 157
Joined: Fri Mar 02, 2012 3:38 pm

Re: Script - Return Weapon to Alter

Post by undeaddemon »

OK... think I have it working again [FYI This is likely a spoiler - for whenever I release this dungeon:
Can you double Check my Scripts?
:oops:

scriptRemoveBlade_1

Code: Select all

function itemCheck(item)
   for champ = 1,4 do
   for slot = 7,8 do
      local x = party:getChampion(champ):getItem(slot)
      if x ~= nil then
      if x.name == item then
         party:getChampion(champ):removeItem(slot)
         returnItem(item,champ,x)
      end
      end   
   end   
   end   
end

function returnItem(item,champ,x)
   for slot = 11,32 do
         if slot < 32 then
            if party:getChampion(champ):getItem(slot) == nil then
               party:getChampion(champ):insertItem(slot,x)
               hudPrint("The Blade of Lightning becomes too painful to hold,")
			   hudPrint("and so is put into "..party:getChampion(champ):getName().."'s bag.")              
			break
            end
         else
            spawn(item,party.level,party.x,party.y,party.facing)
            hudPrint("The Blade of Lightning becomes too painful to hold,")
            hudPrint("and drops to the floor")
            break
         end
   end
end

function checkBlade()
   itemCheck("BladeOfLightning")
end
scriptRemoveBladeDrop_1

Code: Select all

function itemCheck(item)
   for champ = 1,4 do
   for slot = 7,8 do
      local x = party:getChampion(champ):getItem(slot)
      if x ~= nil then
      if x.name == item then
         party:getChampion(champ):removeItem(slot)
         returnItem(item,champ,x)
      end
      end   
   end   
   end   
end

function returnItem(item,champ,x)
            spawn(item,party.level,party.x,party.y,party.facing)
            hudPrint("The Blade of Lightning becomes too painful to hold,")
            hudPrint("and drops to the floor")
            playSound("lightning_bolt_hit")
end

function checkBlade()
   itemCheck("BladeOfLightning")
end
script_ReturnBlade_1

Code: Select all

function itemCheck(item)
   for champ = 1,4 do
   for slot = 7,8 do
      local x = party:getChampion(champ):getItem(slot)
      if x ~= nil then
      if x.name == item then
         party:getChampion(champ):removeItem(slot)
         returnItem(item,champ,x)
      end
      end   
   end   
   end   
end

function returnItem(item,champ,x)
            altar_1:addItem(spawn("BladeOfLightning"))
            hudPrint("The Blade of Lightning yanks from your hand,")
            hudPrint("and flies through the air, out of sight!")
            playSound("lightning_bolt_hit")
end

function checkBlade()
   itemCheck("BladeOfLightning")
end
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: Script - Return Weapon to Alter

Post by Diarmuid »

Don't forget too that timers slow down a lot if not on the same level as the party, so you need to set up a global timer.

I have this in my dungeon, in a central script_entity called coreScript, which controls all global dungeon functions:

Code: Select all

function setCoreTimers(timerInterval)
	levels = getMaxLevels()
	for i = 1, levels do
		spawn("timer", i, 0, 0, 0, "coreTimer_"..i)
			:setTimerInterval(timerInterval)
			:addConnector("activate", "coreScript", "coreTimer")
			:activate()
	end
end

setCoreTimers(0.25)

function coreTimer(sourceTimer)
	if sourceTimer.level == party.level then
		[do whatever you want here]
	end
end
It sets a timer which ticks every quarter of a second, and from there I call any functions like that which check for objects, events, etc.

Put your code in the coreTimer function, ideally bu calling separate functions for different items to keep things clear. And you can setup the interval as you like when you call setCoreTimers.
User avatar
undeaddemon
Posts: 157
Joined: Fri Mar 02, 2012 3:38 pm

Re: Script - Return Weapon to Alter

Post by undeaddemon »

What you have there, seems to be what I originally may have been looking for.
ATM, I am just using pressure plates to call these functions, but if I understand correctly, that I could run a timer to run one of these scripts, and every so often, the Blade would disappear.... ???

Keep in mind, I am a copy and paste artist, no code guy... sadness....
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: Script - Return Weapon to Alter

Post by Diarmuid »

You want the item to return to its altar as soon as it's dropped, right? I'll write you a function tonight and post it with comments to show you how it works. :)
User avatar
undeaddemon
Posts: 157
Joined: Fri Mar 02, 2012 3:38 pm

Re: Script - Return Weapon to Alter

Post by undeaddemon »

Right, what is have manually happening via hidden pressure plate is:
sometimes the champion is forced to put the Blade in Backpack
sometimes the champion is forced to drop the Blade to the ground
sometimes the Blade returns to altar

Return to altar is the big one - and anything you can help with - WOULD BE AWESOME!!

Many Thanks!
:D

UD
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: Script - Return Weapon to Alter

Post by Diarmuid »

There you go:

1. Put the following code in an entity named coreScript.

Code: Select all

-- ***** coreTimer code *****

function setCoreTimers(timerInterval)
	levels = getMaxLevels()
	for i = 1, levels do
		spawn("timer", i, 0, 0, 0, "coreTimer_"..i)
			:setTimerInterval(timerInterval)
			:addConnector("activate", "coreScript", "coreTimer")
			:activate()
	end
end

setCoreTimers(0.25)

function coreTimer(sourceTimer)
	if sourceTimer.level == party.level then
		returnItemToAltar("great_axe", "altar_15")
	end
end

-- ***** returnItem code *****

function returnItemToAltar(itemName, altarId, level)

	-- First an optional level argument. If it's not supplied, set it to party.
	-- This is here to allow an easy call from returnItemToAltarAllLevels()
	
	if level == nil then
		level = party.level
	end
	
	-- Then, check all entities in the current level. Note that
	-- the moment the item is picked up, it disappears from the map.
	
	for i in allEntities(level) do
	
		-- For each entity check if it has the right name.
		
		if i.name == itemName then
		
			-- If we found the name, check if it's not on the altar.
			
			local altar = findEntity(altarId)
			if i.level ~= altar.level or i.x ~= altar.x or i.y ~= altar.y then
				
				-- If the item is not on the altar:
				
				-- 1. Store the id before the item is detroyed. (After, i.id will return an error)
				
				local itemId = i.id
				
				-- 2. If it's an auto generated id, set id to nil to spawn another auto
				--    generated id. If not it crashes. This useful bit of code is by jKos
				
				if (itemId and string.find(itemId, "^%d+$")) then
					itemId = nil
				end
				
				-- 3. Destroy the item
				
				i:destroy()
				
				-- 4. Respawn the item on the altar
								
				altar:addItem(spawn(itemName, nil, nil, nil, nil, itemId))
			end
		end
	end
end

function returnItemToAltarAllLevels(itemName, altarId)
	for level = 1, getMaxLevels() do
		returnItemToAltar(itemName, altarId, level)
	end
end

function pressurePlateReturn()
	returnItemToAltarAllLevels("great_axe", "altar_15")
end

There are two functions main functions to call:
- returnItemToAltar(itemName, altarId) is called every 0.25s and checks to find an item on the current level, and if it finds it not on the altar, it returns it to the altar. It works from the ground, from an alcove, even in flight if you throw it.
- pressurePlateReturn() is intended to be called from a hidden pressure plate just before the player enters the room. This is a safety check, as normally, just looking at the current level is enough, searching through all levels every 1/4s is using CPU for nothing. However, they might be a rare case where the party drops the item in a pit to the level below, or throws it in a teleporter to another level, then goes to the altar: it won't be there. That's why you should run a check on all levels when entering the altar room, just to make sure returnItemToAltar didn't miss it by accident.

To make this work with your item, replace "great_axe" and "altar_15" by your itemName and itemId in the coreTimer function AND in the pressurePlateReturn function.

I've added step by step comments in the code to help you understand it!
Post Reply