[Script] Equip/Unequip Stopper (Fixed)

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

[Script] Equip/Unequip Stopper (Fixed)

Post by Diarmuid »

Hi there,

Just developped this for my dungeon and though it could be useful to others.

The new onEquipItem and onUnequipItem hooks do not unfortunately have a "return false" option which would prevent the player from putting the item in or removing the item from an inventory slot. So here's my solution:

1. Put this in a script entity named equipStopper:
SpoilerShow

Code: Select all

-- Diarmuid's Equip/Unequip Stopper
-- v1.0

timersTable = {}

function stopEquip(champion, slot)
	-- Remove item
	champion:removeItem(slot)
	-- Call delay function
	item = getMouseItem()
	createDelayTimer(item.name, item.id, champion:getOrdinal(), slot, "equip")
end

function stopUnequip(champion, slot)
	-- Remove item
	setMouseItem(nil)
	-- Call delay function
	item = champion:getItem(slot)
	createDelayTimer(item.name, item.id, champion:getOrdinal(), slot, "unequip")
end

function createDelayTimer(itemName, itemId, championOrdinal, slot, type)
	-- Create Timer
	local timerId = itemId..".delay"
	if findEntity(timerId) ~= nil then
		findEntity(timerId):destroy()
	end
	local delayTimer = spawn("timer", party.level, party.x, party.y, 0, timerId)
	delayTimer:addConnector('activate', 'equipStopper', 'timerCallback')
	delayTimer:setTimerInterval(0.01)
	delayTimer:activate()
	
	-- Pack timer callback arguments
	timersTable[timerId] = {}
	timersTable[timerId].itemName = itemName
	timersTable[timerId].itemId = itemId
	timersTable[timerId].championOrdinal = championOrdinal
	timersTable[timerId].slot = slot
	timersTable[timerId].type = type
end

function timerCallback(self)
	-- Unpack timer callback arguments
	timerId = self.id
	itemName = timersTable[timerId].itemName
	itemId = timersTable[timerId].itemId
	championOrdinal = timersTable[timerId].championOrdinal
	slot = timersTable[timerId].slot
	type = timersTable[timerId].type

	-- Numerical Id renamer by jKos
	if (itemId and string.find(itemId, "^%d+$")) then
		itemId = nil
	end
	
	-- Respawn item
	if type == "equip" then
		setMouseItem(spawn(itemName, nil, nil, nil, nil, itemId))
	elseif type == "unequip" then
		local champion
		for i = 1,4 do
			if party:getChampion(i):getOrdinal() == championOrdinal then
				champion = party:getChampion(i)
			end
		end
		champion:insertItem(slot,spawn(itemName, nil, nil, nil, nil, itemId))
	end
	
	-- Destroy timer
	self:destroy()
end
2. Call one of the following functions from onEquipItem or onUnequipItem hooks:
- equipStopper.stopEquip(champion, slot)
- equipStopper.stopUnequip(champion, slot)


How it works:
- This code first removes the item from the slot/mouse it was put it (equivalent to :destroy(), the item doesn't exist anymore).
- Then it respawns the item in its original place 0.01s later, giving the illusion that the item was never moved. This can for example prevent a champion from equipping a Sword of Chivalry until annointed knight by a King, or prevent putting a torch in hand in a darkness zone, or putting a magical stone in a fighter or rogue inventory, or whatever you can think of. EDIT: Or create cursed items, thanks Neikun.

The delay is crucial, as the game seems to remove the item after the hook has finished executing. So if you put the item back right away, it gets deleted.

Example, using Balthasar's test object:

Code: Select all

cloneObject{
	name = "curse_cap",
	baseObject = "peasant_cap",
	uiName = "Cursed Hat",
	onUnequipItem = function(champion, slot)
		if slot == 1 then
			hudPrint("This hat is cursed!")
			equipStopper.stopUnequip(champion, slot)
		end
	end
}
Last edited by Diarmuid on Fri Dec 28, 2012 6:57 am, edited 10 times in total.
User avatar
Neikun
Posts: 2457
Joined: Thu Sep 13, 2012 1:06 pm
Location: New Brunswick, Canada
Contact:

Re: [Script] Cancel item equip + Delay

Post by Neikun »

Could this be adapted to stop the player from unequiping and item? (cursed :twisted: )
"I'm okay with being referred to as a goddess."
Community Model Request Thread
See what I'm working on right now: Neikun's Workshop
Lead Coordinator for Legends of the Northern Realms Project
  • Message me to join in!
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: [Script] Cancel item equip + Delay

Post by Diarmuid »

Good idea, Neikun. I've added the reverse script.
Last edited by Diarmuid on Fri Dec 28, 2012 3:02 am, edited 1 time in total.
Balthasar
Posts: 32
Joined: Sun Dec 09, 2012 1:53 am

Re: [Script] Cancel item equip/unequip + Delay

Post by Balthasar »

I tried this, it crashes for me every time I equip the item. (Or unequip the 'cursed' version.)
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: [Script] Cancel item equip/unequip + Delay

Post by Diarmuid »

Hmmm both worked for me... Did you:
- install LoG framework?
- copy the delay code in a script entity and change "exsp" to your script entity id?

How did you add the hooks to items? In lua definitions or dynamically?

You can also paste here your script I'll try to see whats wrong!
Balthasar
Posts: 32
Joined: Sun Dec 09, 2012 1:53 am

Re: [Script] Cancel item equip/unequip + Delay

Post by Balthasar »

I put this into my items.lua:

Code: Select all

cloneObject{
name = "curse_cap",
baseObject = "peasant_cap",
uiName = "Cursed Hat",
    onUnequipItem = function(self, champion, slot)

          setMouseItem(nil)
          delayscript.mydelay(0.1,
             function(self, name, id, championOrd, slot)
                local champion = grimq.getChampionFromOrdinal(championOrd)
                champion:insertItem(slot,spawn(name, nil, nil, nil, nil, id))
             end,
             {self.name,self.id,champion:getOrdinal(),slot}
          )

    end

}
And I have a script entity called "delayscript" with this in it:

Code: Select all

    exspCtr = 0
    exspCtrLimit = 2000

    function autoCtr()
       exspCtr = (exspCtr + 1)%exspCtrLimit
       return exspCtr
    end

    function mydelay(delay, funct, args)
       local delayTimer = timers:create('delayTimer.'..autoCtr())
       delayTimer:setTimerInterval(delay)
       delayTimer:addCallback(funct,args)
       delayTimer:setTickLimit(1,true)
       delayTimer:activate()
    end
I originally didn't have the LoG Framework, but I have it installed now. Still crashes every time I unequip the item.

I am new to this so it is probably my own fault.
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: [Script] Equip/Unequip Stopper (Fixed)

Post by Diarmuid »

Code fixed!

I'm sorry for all the fuss, this script is finally in a working state (and I've removed all previous misleading code from this thread).

It all started with a misunderstanding - I wrongly assumed that onEquipItem would return (self, champion, slot), like all other asset hooks which return themselves as the first argument. But drinking Glögg while coding (credit to jKos for the joke) gets you two hooks which return only (champion, slot).

But then my code still worked because jKos went ahead and fixed petri's error in the LoG framework, so dynamic hooks there were returning (self,...), but then my script wasn't compatible with vanilla hooks which didn't. If you've lost track, don't worry. :shock: :?

Anyway... I've updated my script, so everything should be fine. Let's curse those armors!

Thanks for your patience! ;)

EDIT: Not that dynamic equip/unequip hooks in the framework will remain (self, champion, slot), but you can use these functions the same way.
carlos2000
Posts: 7
Joined: Mon Jan 19, 2015 10:46 am

Re: [Script] Equip/Unequip Stopper (Fixed)

Post by carlos2000 »

great idea Diarmuid,
I am just having troubles when I put the curse item over existing equipped item - and vice versa.
(game crash resp cursed item disappers)
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: [Script] Equip/Unequip Stopper (Fixed)

Post by Diarmuid »

Ha yes indeed I remember there was an error with that script in its original version. We fixed it for the ORRR2, I'll try to check if I can find the code and I'll post a fixed version here.
Post Reply