Firstly, without the help of MrChoke, Prozail and jKos, from this thread viewtopic.php?f=22&t=8405...
I would still be pulling my hair out Im sure, thanks guys for the keylocked chest definition
Also thank you jKos again for the "script_autotrigger"
This thread is for if you want to:
1. Have a locks and traps skill
2. Base the success of picklocking a locked chest on champions class and locks and traps skill
3. Have your chests trapped
4. Have your champions (need class and locks/traps skill) to be able to discover and disarm the trap.
Locks and Traps skill (init.lua or create and import skills.lua)
SpoilerShow
Code: Select all
defineSkill{
name = "locks_traps",
uiName = "Locks and Traps",
priority = 170,
icon = 32,
description = "Champion is able to pick locks, spot and disarm traps.",
},
}
SpoilerShow
Code: Select all
defineObject{
name = "chest_keylocked",
baseObject = "chest",
components = {
{
class = "Script",
name = "data",
source = [[
data = {}
function get(self,name)
return self.data[name]
end
function set(self,name,value)
self.data[name] = value
end
]],
},
{
class = "Lock",
name = "keyLock"
},
{
class = "Clickable",
offset = vec(0,0.5,0),
size = vec(1.5, 1.0, 1.0),
maxDistance = 1,
onClick = function(self)
if not self.go.chest:getLocked() then
if self.go:getComponent("keyLock") then
self.go:removeComponent("keyLock")
end
chestScript.script.trapCheck(self)
return true
else
local used_item = getMouseItem()
if not self.go.chest:getLocked() then
chestScript.script.trapCheck(self)
return false
end
if used_item == nil then
chestScript.script.trapCheck(self)
return false
end
local stackSize = used_item:getStackSize()
if used_item.go.name == 'lock_pick' then
setMouseItem(nil)
playSound("lock_incorrect")
hudPrint("This chest requires a key and cannot be picked.")
delayedCall("chestScript", 0.2, "delayedGiveLockPick", used_item.go.name, stackSize)
chestScript.script.trapCheck(self)
return false
elseif not used_item.go.item:hasTrait("key") then
hudPrint("You must open the chest with a key.")
chestScript.script.trapCheck(self)
return false
elseif self.go.keyLock:getOpenedBy() == used_item.go.name then
self.go.chest:setLocked(false)
setMouseItem(nil)
self.go.lock:disable()
playSound("key_lock")
self.go:removeComponent("keyLock")
-- If you don't want the key back, remove the line below
--delayedCall("chestScript", 0.2, "delayedGiveLockPick", used_item.go.name)
chestScript.script.trapCheck(self)
return true
else
hudPrint("Not the right key.")
playSound("key_lock_faint")
chestScript.script.trapCheck(self)
return false
end
end
end,
},
},
}
defineObject{
name = "chest_picklock",
baseObject = "chest",
components = {
{
class = "Script",
name = "data",
source = [[
data = {}
function get(self,name)
return self.data[name]
end
function set(self,name,value)
self.data[name] = value
end
]],
},
{
class = "Lock",
name = "keyLock"
},
{
class = "Clickable",
offset = vec(0,0.5,0),
size = vec(1.5, 1.0, 1.0),
maxDistance = 1,
onClick = function(self)
if not self.go.chest:getLocked() then
if self.go:getComponent("keyLock") then
self.go:removeComponent("keyLock")
end
chestScript.script.trapCheck(self)
return true
else
local used_item = getMouseItem()
if not self.go.chest:getLocked() then
chestScript.script.trapCheck(self)
return false
end
if used_item == nil then
chestScript.script.trapCheck(self)
return false
end
local stackSize = used_item:getStackSize()
if used_item.go.name == 'lock_pick' then
for i = 1,4 do
local c = party.party:getChampion(i)
local cLocks = c:getSkillLevel("locks_traps")
local cDex = c:getBaseStat("dexterity")
local cClass = c:getClass()
if cLocks ~= nil then
if cClass == "rogue" then
--or cClass == "ninja"
--or cClass == "mechanic"
--or cClass == "tomb_raider"
--or cClass == "pirate" --change to reflect which class is able to discover traps
if math.random(1,100) <= (cDex * cLocks) then
hudPrint(""..c:getName().." picked the lock!")
self.go.chest:setLocked(false)
setMouseItem(nil)
self.go.lock:disable()
playSound("key_lock")
self.go:removeComponent("keyLock")
chestScript.script.trapCheck(self)
local lockpick = spawn("lock_pick",party.level,party.x,party.y,party.elevation)
if stackSize == 1 then
return true
else
lockpick.item:setStackSize(stackSize - 1)
setMouseItem(lockpick.item)
return true
end
else
setMouseItem(nil)
playSound("lock_incorrect")
hudPrint(""..c:getName().." failed to pick the lock...")
delayedCall("chestScript", 0.2, "delayedGiveLockPick", used_item.go.name, stackSize)
chestScript.script.trapCheck(self)
return false
end
else
setMouseItem(nil)
playSound("lock_incorrect")
hudPrint(""..c:getName().."'s class can not use lockpicks...")
delayedCall("chestScript", 0.2, "delayedGiveLockPick", used_item.go.name, stackSize)
chestScript.script.trapCheck(self)
return false
end
else
setMouseItem(nil)
playSound("lock_incorrect")
hudPrint("No one has Locks and Traps skill above 0...")
delayedCall("chestScript", 0.2, "delayedGiveLockPick", used_item.go.name, stackSize)
chestScript.script.trapCheck(self)
return false
end
end
elseif used_item.go.item:hasTrait("key") then
hudPrint("This chest can only be picklocked...")
chestScript.script.trapCheck(self)
return false
else
hudPrint("This chest can only be picklocked...")
playSound("key_lock_faint")
chestScript.script.trapCheck(self)
return false
end
end
end,
},
},
}
SpoilerShow
Code: Select all
defineObject{
name = "toolkit",
baseObject = "base_item",
components = {
{
class = "Model",
model = "assets/models/items/lockpicks.fbx",
},
{
class = "Item",
uiName = "Tool Kit",
description = "Tools for disarming traps.",
gfxIndex = 356,
impactSound = "impact_blade",
weight = 3,
primaryAction = "disarm",
traits = { "usable", "two_handed" },
},
{
class = "ItemAction",
name = "disarm",
uiName = "Disarm",
cooldown = 4,
onAttack = function(self, champion, slot)
local dx,dy = getForward(party.facing)
local cClass = champion:getClass()
if cClass == "rogue" then
--or cClass == "ninja"
--or cClass == "mechanic"
--or cClass == "tomb_raider"
--or cClass == "pirate" --change to reflect which class is able to disarm traps
for e in party.map:entitiesAt(party.x + dx, party.y + dy) do
if e.chest and e.data then
if e.data:get("trapped") then
return chestScript.script.disarmTrap(self, champion, slot, e)
else
hudPrint("The chest is not trapped...")
return false
end
else
hudPrint("There is no trap here.")
return false
end
end
else
hudPrint(""..champion:getName().." can not use the toolkit.")
return false
end
end,
},
},
}
SpoilerShow
Code: Select all
defineObject{
name = 'script_autotrigger',
baseObject = 'script_entity',
components = {
{
class = 'FloorTrigger'
},
{
class = "Script",
source = [[
function execute(trigger)
-- your code here
end
self.go.floortrigger:addConnector('onActivate',self.go.id,'execute')
]]
},
}
}
SpoilerShow
Code: Select all
defineObject{
name = "party",
baseObject = "party",
components = {
{
class = "Party",
onMove = function(party,dir)
--print(party.go.id,"moving to",dir)
local t = findEntity("toolkitTimer")
if t ~= nil then
return chestScript.script.disarmStop()
end
end,
onTurn = function(party,dir,arg1)
--print(party.go.id,"turning to",dir)
local t = findEntity("toolkitTimer")
if t ~= nil then
return chestScript.script.disarmStop()
end
end,
onDie = function(party,champion)
local t = findEntity("toolkitTimer")
if t ~= nil then
return chestScript.script.disarmStop()
end
end,
onRest = function(party)
--print(party.go.id,'is resting')
local t = findEntity("toolkitTimer")
if t ~= nil then
return chestScript.script.disarmStop()
end
end,
}
},
}
SpoilerShow
Code: Select all
----------------------------------------------------------checkChampion()
function checkChampion()
for i = 1,4 do
local c = party.party:getChampion(i)
local cLocks = c:getSkillLevel("locks_traps")
local cClass = c:getClass()
if cClass == "rogue" then
--or cClass == "ninja"
--or cClass == "mechanic"
--or cClass == "tomb_raider"
--or cClass == "pirate" --change to reflect which class is able to discover traps
if cLocks > 0 then
return true
end
end
return false
end
end
--------------------------------------------------------------------------------get lock picks back!
function delayedGiveLockPick(itemName, stackSize)
local lockpick = spawn(itemName,party.level,party.x,party.y,party.elevation)
if stackSize then
lockpick.item:setStackSize(stackSize)
end
setMouseItem(lockpick.item)
end
-------------------------------------------------------------------------------trapCheck(self)
function trapCheck(self)
if self.go.data:get("trapped") then
spawner_1.spawner:activate() -- enter your own trap script here
hudPrint("trap goes off...")
if math.random(1,10) <= self.go.data:get("recurring") then
hudPrint("...and is still armed!")
else
self.go.data:set("recurring",0)
self.go.data:set("trapped",false)
hudPrint("...and has not re-armed.")
end
end
end
---------------------------------------------------------------------------------------disarming scripts
interruptedDisarm = false
-------------------------------------------------------disarmTrap(self, champion, slot)
function disarmTrap(self, champion, slot)
local t = findEntity("toolkitTimer")
if t ~= nil then
t:destroy()
end
interruptedDisarm = false
GameMode.fadeOut(0, 2)
playSound("lock_incorrect")
hudPrint(""..champion:getName().." is attempting to disarm the trap...")
spawn("timer",party.level,party.x,party.y,party.elevation,party.facing,"toolkitTimer")
toolkitTimer.timer:setTimerInterval(4)
toolkitTimer.timer:start()
delayedCall("chestScript", 4, "disarmResult", champion, champion:getSkillLevel("locks_traps"))
end
------------------------------------------------------disarmResult(champion, skill)
function disarmResult(champion, skill)
local t = findEntity("toolkitTimer")
if t ~= nil then
t:destroy()
end
if interruptedDisarm == true then
return false
end
GameMode.fadeIn(1, 0.1)
if math.random(1,10) <= skill then
local dx,dy = getForward(party.facing)
for e in party.map:entitiesAt(party.x + dx, party.y + dy) do
if e.chest and e.data then
e.data:set("trapped",false)
e.data:set("recurring",0)
end
end
playSound("key_lock")
hudPrint(""..champion:getName().." disarmed the trap!")
else
for s in party.map:entitiesAt(party.x, party.y) do
if s.script and s.floortrigger then
s.script:trap(self)
end
end
playSound("lock_incorrect")
hudPrint(""..champion:getName().." failed to disarm the trap.")
end
end
------------------------------------------------------------disarmStop()
function disarmStop()
local t = findEntity("toolkitTimer")
if t ~= nil then
t:destroy()
end
interruptedDisarm = true
GameMode.fadeIn(1, 0.1)
hudPrint("Disarming interrupted...")
end
TO SET UP A TRAPPED KEYLOCK CHEST
1. Place a chest_keylocked into your dungeon
2. tick the locked and keylocked checkboxes, also enter in the key you want the chest to be openned by
2. Place a script_autotrigger in front of the chest with this script in it
SpoilerShow
Code: Select all
function execute(trigger)
if chest_keylocked_1.data:get("trapped") == false then
if chestScript.script.checkChampion() == true then
hudPrint("This chest is not trapped...")
end
else
chest_keylocked_1.data:set("trapped",true)
chest_keylocked_1.data:set("recurring",5) --change the recurring to alter whether the trap will be re-armed when you set it off (1 rarely, 10 always)
if chestScript.script.checkChampion() == true then
hudPrint("This chest is trapped!")
end
end
end
self.go.floortrigger:addConnector('onActivate',self.go.id,'execute')
function trap(trigger)
spawner_1.spawner:activate() -- enter your own trap script here
end
4. change the chest_keylocked_1.data:set("recurring",5) line to alter whether the trap will be re-armed when you set it off (1 rarely re-arms, 10 always rearms)
5. Currently only Rogues will be able to do all of the above.... --change to reflect which class is able to discover traps
When party steps onto the script_autotrigger, chestScript.script.checkChampion() will check to see if a champ is off the right class and whether they have Locks and Traps skill > 0
If they do a hudPrint msg should inform you of whether the chest is trapped or not (not re-armed). If you dont then no msg is given (they do not spot the trap)
Then onClick will set the trap off.... based on the recurring value, the trap will either re-arm or not.
You will then need the correct key to open the chest.
Every time you try to open the chest with any key the trap script of the script_autotrigger will go off (if the trap is still armed)
---------------------------------------------------------------------------------------------
TO SET UP A TRAPPED PICKLOCK CHEST
1. Place a chest_picklock into your dungeon
2. tick the locked and keylocked checkboxes
2. Place a script_autotrigger in front of the chest with this script in it
SpoilerShow
Code: Select all
function execute(trigger)
if chest_picklock_1.data:get("trapped") == false then
if chestScript.script.checkChampion() == true then
hudPrint("This chest is not trapped...")
end
else
chest_picklock_1.data:set("trapped",true)
chest_picklock_1.data:set("recurring",5) --change the recurring to alter whether the trap will be re-armed when you set it off (1 rarely rearm, 10 always rearmed)
if chestScript.script.checkChampion() == true then
hudPrint("This chest is trapped!")
end
end
end
self.go.floortrigger:addConnector('onActivate',self.go.id,'execute')
function trap(trigger)
spawner_1.spawner:activate() -- enter your own trap script here
end
4. change the chest_picklock_1.data:set("recurring",5) line to alter whether the trap will be re-armed when you set it off (1 rarely re-arms, 10 always rearms)
5. Currently only Rogues will be able to do all of the above.... --change to reflect which class is able to discover traps
When party steps onto the script_autotrigger, chestScript.script.checkChampion() will check to see if a champ is off the right class and whether they have Locks and Traps skill > 0
If they do a hudPrint msg should inform you of whether the chest is trapped or not (not re-armed). If you dont then no msg is given (they do not spot the trap)
Then onClick will set the trap off.... based on the recurring value, the trap will either re-arm or not.
You will then need a picklock to open the chest.
When you attempt to pick the chest lock champions Locks and Traps skill x champion Dexterity is used (if math.random(1,100) <= (cDex * cLocks) then)
If they fail, you do not lose the lockpick... and every time you try to pick the lock the trap script of the script_autotrigger will go off (if the trap is still armed)
---------------------------------------------------------------------------------------------
DISARMING THE TRAP
All you need to do is stand in front of the chest and "attack" with the Tool Kit in hand.
The chance of disarming is simply (if math.random(1,10) <= locks and traps skill then)
It will fade in and out like you are digging and you can interrupt the disarming process by either moving, turning, resting or dying (you may want to add attacking or being damaged to that list??)
If you fail the trap will go off, if you succeed then the trap is removed (chest_picklock_1.data:set("trapped",true) )
---------------------------------------------------------------------------------------------
Room for improvement-
1. Not sure how to enforce a cooldown on all champs like the digging fade out does... nor have I used any GUI digging... etc
2. Tool Kit just looks like a picklock for now
3. Only key locked and key incorrect sounds are used... I will find some other sounds soon
4. An appropraite icon for the Locks and Traps skill
5. I am not sure how to work it so that the champion with the highest Locks and Traps skill is used... now it just cycles through and uses the first champ who has the right class and Locks and Traps skill > 0
I am sure it is an easy fix but I have screwed around with it for a while to no avail.... help maybe??
Let me know how you go, or if there is anything I have missed
Akroma