CODING ADVICE NEEDED!

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
User avatar
WaspUK1966
Posts: 135
Joined: Sat Aug 09, 2014 9:17 am

CODING ADVICE NEEDED!

Post by WaspUK1966 »

I have written the following script that makes a random champion say something when triggered:

Code: Select all

function champspeech()
x = math.random(1,4)
if party:getChampion(x):isAlive() then
local Name1 = party:getChampion(x):getName()
hudPrint(""..Name1.." whispers: WHAT was that?..")
playSound("secret")
else
end
end
In it's present form, if the random champion IS ALIVE then the script prints to the screen. However, if the random champion is dead or not enabled, the script will end. I want to code it so that, if the chosen champion is dead , it will then keep looping (generating random numbers 1 thru 4 ), until it finds a champion that is still alive, and then runs the code, rather than just end as it does now. Any advice?

Thanks

George
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: CODING ADVICE NEEDED!

Post by Komag »

Code: Select all

function champspeech()
x = math.random(1,4)
if party:getChampion(x):isAlive() then
local Name1 = party:getChampion(x):getName()
hudPrint(""..Name1.." whispers: WHAT was that?..")
playSound("secret")
else
end
end
I'm not up to snuff with Grimrock 2 Lua, but you might try check for NOT isAlive(), and if it finds that the champion is dead, go back to the start of the function. Or maybe try a While loop with a variable "itsAlive":
itsAlive = FALSE
WHILE itsAlive = FALSE DO
x = math.random(1,4)
if party:getChampion(x):isAlive() then itsAlive = TRUE
END

I'm sure some of that syntax is wrong
Finished Dungeons - complete mods to play
User avatar
WaspUK1966
Posts: 135
Joined: Sat Aug 09, 2014 9:17 am

Re: CODING ADVICE NEEDED!

Post by WaspUK1966 »

Thanks for the reply, Komag. I should have stated that this code is for LOG 1, not the sequel. Does that help?

George
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: CODING ADVICE NEEDED!

Post by Komag »

Not really, but the concept should be the same, maybe the exact code even
Finished Dungeons - complete mods to play
bitcpy
Posts: 39
Joined: Tue Apr 24, 2012 7:43 pm

Re: CODING ADVICE NEEDED!

Post by bitcpy »

For a small data-set it doesn't really matter if you would loop until finding a champion alive or if you would randomize a value inside a known list of valid indices.
But pretend you would have a list of one hundred thousand indices, half of them having the state 'alive' and the rest being counted as 'dead'.
Looping until finding an 'alive' index could take you some time, if you're unlucky in that case.

I'd suggest you figure out what champions are alive, then randomize in that set.
It could look something like this,

Code: Select all

function champspeech()
	-- build a list of alive champions
	local champIds = {}
	for i = 1, 4 do
		if party:getChampion(i):isAlive() then
			table.insert(champIds, i)
		end
	end
	
	-- only allow a champion to speech if anyone was actually alive
	local num = table.getn(champIds)
	if num > 0 then
		-- fetch a random champion from the list of alive ones
		local x = math.random(1,num)
		local champId = champIds[x]
		local champName = party:getChampion(champId):getName()
		
		-- print information to screen that the champion found something
		hudPrint( champName .. " whispers: WHAT was that?" )
		playSound("secret")
	end
end
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: CODING ADVICE NEEDED!

Post by Komag »

I agree that's actually the best way for a longer set, I thought of it but figured it was overkill in this case. One problem with my simpler option, though, is if all four champions are dead (and you don't let the game be over), it would loop forever. Probably not an issue though unless you plan to allow a full dead party to keep playing.
Finished Dungeons - complete mods to play
User avatar
Isaac
Posts: 3191
Joined: Fri Mar 02, 2012 10:02 pm

Re: CODING ADVICE NEEDED!

Post by Isaac »

You can try this in a script. You can call it with optional arguments, or just link directly to it with a plate or switch.

* Try calling it with: speak("We are locked in!", "shouts", 3, "gate_lock")
* includes a help function: script_name:help()

Code: Select all

discern_triggers = true  --set false to disable special handling of button and switches

function speak(caller, message, action, ordinal, secret, option)  --ordinal nil for random champion; secret and option are booleans
	local ordinal = ordinal or math.random(4)
			 --=-------------------------------------------------------------------------------[check for live PC]--		
	for x = 0,3 do
		local z = (((ordinal - 1) + x) % 4) +1
		local champion = party:getChampion(z)    
		if champion:isAlive() then
			local message = message or _randomAlert() --=-----[ensures default values]--
			if option then 
				message = _randomAction().." "..message
			else
				local action = action or "says"
				message = action..": "..message	
			end
			if discern_triggers and _isSwitch(caller) then  --=---------------------[button/switch check]--
				message, secret = _buttonSpeak(caller, champion)
			end 
			if secret then --=--------------------------------[check for sound and then print to screen]--
				if type(secret) == "string" then
					 playSound(secret)
				else playSound("secret")
				end 
			end
			hudPrint(tostring(champion:getName().." "..message))
			break	
		end
	end	
end


function _buttonSpeak(caller, champion)
--=-----------------------------------------------------------[special handling for switches]--
	--Ids and messages for the connected switches, and optional sound effect.
	local switch_trigger_data = {			--switch id,		 --action,	  --message, --sound
									"pressure_plate_hidden_1", "shouts" , _randomAlert(3), "", 						    	  --no sound																		  -- no sound
									"pressure_plate_hidden_2", _randomAction(), _randomAlert(), "secret",					  -- secret sound
									"pressure_plate_hidden_3", "yells", "OUCH! I think I stepped on a tack.", "default_pain", --correct PC pain sound
								}
	local secret
	local message						
	for t = 1, #switch_trigger_data, 4 do
		if caller.id == switch_trigger_data[t] then					
			message = switch_trigger_data[t+1]..": "..switch_trigger_data[t+2]
			if  switch_trigger_data[t+3] == "default_pain" then 
				champion:playDamageSound()
			elseif switch_trigger_data[t+3] ~= "" then
				secret = switch_trigger_data[t+3]
			end
			break
		end
	end
	return message, secret
end

--=-----------------------------------------------[utilities]--
function _isSwitch(target)
	local switches = {  "Receptor", "Lock",	"Lever", "Button", "PressurePlate",
						"Alcove", "Counter", "Timer", "TorchHolder",
					 }
	for check = 1,#switches do
		if switches[check]	== target.class then
		return true
		end	
	end
end

function _randomAlert(pick) 
	local response = {"WHAT was that?", "Did you hear that?", "I heard something!", } --You can add as many responses to the list as you like; same with the actions.
	if pick and type(pick) == "number" and pick <= #response then 
		return " "..response[pick]	
	end 
	return " "..response[math.random(#response)]
end

function _randomAction(pick) 
	local response = {"wispers", "says", "[startled] says", }  
	if pick and type(pick) == "number" and pick <= #response then 
		return " "..response[pick]	
	end 
	return " "..response[math.random(#response)]
end

function help()
	print("Usage: speak(self, message, action, ordinal, secret, optional_expression)")
	print("All arguments are optional, and any argument can be nil.")
	print("Calling speak() will pick a champion and print their [random] announcement.")
	print("")
	print("Calling speak(\"Hello!\"), will use the given string as a random champion's statement.")
	print("")
	print("Calling speak(\"Hello!\", \"screams\"), will use \"screams\" instead of the default \"says\".")
	print("")
	print("Calling speak(\"Hello!\",nil,2), will choose champion [ordinal] 2 as the speaker; and use the default \"says\".")
	print("")
	print("Calling speak(\"Hello!\",nil,nil,[any non-string input]), will play the \"secret\" sound; or...")
	print("You may enter the name of ant valid sound effect [in quotes] to play instead of the default of \"secret\".")
	print("")
	print("Calling speak(nil,nil,nil,\"gate_lock\", true), will play the \"gate_lock\" sound, and have a random champion")
	print("exclaim a random alert.")
end

User avatar
WaspUK1966
Posts: 135
Joined: Sat Aug 09, 2014 9:17 am

Re: CODING ADVICE NEEDED!

Post by WaspUK1966 »

Thank you everyone for all your input. Really appreciate it. Everyone on this forum is so helpful. People seemed to like my first game, OGRE, so I`m working hard on the sequel. I`m trying to make my games different from what's already out there, and like to try new stuff that will surprise people. So this code should come in handy.

Once again (until the next time I need help! lol!), thank you everyone.

George
Post Reply