Champion Capture / Rescue Script [MOD]

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
User avatar
pferguso
Posts: 40
Joined: Tue Nov 06, 2012 6:09 pm

Champion Capture / Rescue Script [MOD]

Post by pferguso »

Hello all. I wanted to share a script I wrote a while back. So let's say you have a dungeon with some jail cells scattered about. Think of these like rescue closets from Left 4 Dead. So one of your party members get's all of their health beat out of them by a bad guy. Why kill him? Make him get captured instead! This way, you can rescue him. To do this script, you need essentially 3 things. I will give you two of them, but you're going to have to get creative with the third thing:

1. The rescue script. Create a script entity in your dungeon and name it "rescue_script" include the following code in it:
SpoilerShow
cells = {0,0,0,0,0}
prisonerLocations = {{5,10}, {11,14}, {11,18}, {13,24}, {3,24}} --these are custom to your own dungeon
prisonerFacings = {0,0,2,0,1}
cellDoorLocations = {{4, 11},{13,16},{13,19},{12, 21},{4, 21}} --these are custom to your own dungeon

function clearCell()
local i = 1
while i < 6 do
if prisonerLocations[1] == party.x and prisonerLocations[2] == party.y then
cells = 0
--print("cell cleared.")
end
i = i + 1
end
end

function sendToPrison()
local myNum = math.random(1, 5)
while cells[myNum] == 1 do
myNum = math.random(1, 5)
end
--print("sendToPrison(): area: "..myNum.."")
cells[myNum] = 1
--shootProjectile(projectile, level, x, y, direction, speed, gravity, velocityUp, offsetX, offsetY, offsetZ, attackPower, ignoreEntity, fragile)
shootProjectile("rescue_icon", 6, prisonerLocations[myNum][1], prisonerLocations[myNum][2], prisonerFacings[myNum], 0, 0, 0, 0, 0, 0, 0, party, true)
local doors = entitiesAt(6, cellDoorLocations[myNum][1], cellDoorLocations[myNum][2])
for i in doors do
if i.name == "prison_door_portcullis" then
i:close()
end
end
end

function notifyRescuePartyMember(sender)
--print("party member rescued")
playSound("level_up")
clearCell()
local i = 1
while i <= 4 do
local champion = party:getChampion(i)
if champion:getEnabled() == false then
champion:setEnabled(true)
champion:setStat("health", champion:getStatMax("health") / 2)
--champion:setStat("health", 0)
hudPrint(""..champion:getName().." has joined the party.")
doRandomRescueChatter(champion)
return
end
i = i + 1
end
end

function notifyChampionCaptured(sender, ordinal)
local utils = findEntity("utils")
--print("notifyChampionCaptured: "..ordinal.."")
local champion = getChampionFromOrdinal(ordinal)
if champion then
hudPrint(""..champion:getName().." has been captured.")
champion:setEnabled(false)
sendToPrison()
end
end

function doRandomRescueChatter(champion)
local c = party:getChampion(math.random(1,4))

while c:getEnabled() == false or c == champion or c:isAlive() == false do
c = party:getChampion(math.random(1,4))
end

local myNum = math.random(1,4)

if myNum == 1 then
hudPrint(""..champion:getName()..": Thank you, my friends!\n"..c:getName()..": Welcome back!")
elseif myNum == 2 then
hudPrint(""..c:getName()..": Are you alright?\n"..champion:getName()..": I'm better now that you are here!")
elseif myNum == 3 then
hudPrint(""..champion:getName()..": I hope I didn't miss anything. Let us continue...")
elseif myNum == 4 then
hudPrint(""..champion:getName()..": You came back for me!\n"..c:getName()..": You would do the same for us, "..champion:getName()..". Now let's move out!")
end
end

function getChampionFromOrdinal(ord)
local i = 1
while i <= 4 do
local champion = party:getChampion(i)
if champion:getOrdinal() == ord then
return champion
end
i = i + 1
end
end


2. A Custom party, with a couple hooks in it. This could be called MyCustomParty.lua. Make sure you include this in your init.lua script as well.
SpoilerShow
cloneObject{
name = "party",
baseObject = "party",

onProjectileHit = function(champion, projectile, amount)
if projectile.name == "rescue_icon" then
local rescue_script = findEntity("rescue_script")
if rescue_script then
rescue_script:notifyRescuePartyMember()
end
return false
end
return true
end,

onDie = function (champion)
local rescue_script = findEntity("rescue_script")
if rescue_script then
local o = champion:getOrdinal()
rescue_script:notifyChampionCaptured(o)
end
return true
end,
}


3. A custom object representing the captured party member. This is a 3D mesh, but it can be a spinning icon with a question mark on it if you like.
Make sure you define this "rescue_icon" on your items.lua file:
SpoilerShow
defineObject{
name = "rescue_icon",
class = "Item",
uiName = "Rescue Icon",
--gfxAtlas = "my_icons_icons.tga",
--gfxIndex = 3,
castShadow = true,
model = "mod_assets/models/rescue_icon.fbx",
weight = 0.1,
projectileRotationSpeed = 0,
}


Here is a link to a video of the script in action, as well as some commentary on the code:
http://youtu.be/PFQevJZvgTU

As always, comments and questions are welcome and encouraged. Enjoy!
Alcator
Posts: 37
Joined: Fri Apr 13, 2012 9:59 am

Re: Champion Capture / Rescue Script [MOD]

Post by Alcator »

It's cool, and would be even cooler if you'd make the silhouette asset available for others :-)

Question: Doesn't this make death actually preferable to healing? (Thinking crystals etc.) Because when you picked the hero back, she had full health... Might want to tweak it by giving the rescued hero 1 hp or something like that?
Post Reply