Page 1 of 1

A thank you and a script question

Posted: Thu Apr 19, 2018 2:47 pm
by Curunir
Hello, wonderful people!

I've been away for quite a few years but I sat down to play Grimrock 2 again AND mod it for the first time. I spent the last week combing through the entire GR2 modding forum and I learnt a whole lot about how scripting works (I have zero experience with code, outside of scripting a couple of weapons in ZDoom's DECORATE).

First and foremost, a huge thank you! to the devs and all the great folks on the forum who have published so much script material and helped others so much!

Now to the meat of the problem - I'm trying to make a section inspired by classic D&D dungeon White Plume Mouintainsection, where the further you go down a corridor, the more your items heat up, starting to do increasingly greater damage the further you go. The original dungeon forced everyone to drop their metal items and gear, but I think just the weapons will do in Grimrock.

What I'm trying to do is come up with a script that checks if the party has any weapons in their hand slots or inventory, and if they do have any, a number of increasingly more damaging damageTiles are called up, with the 2 flag for ongoing damage to keep the damage up if you stay on the tile (if I understand correctly what 'ongoing' is).

However, I have no idea how to check for weapons. I found scripts on the forums that DO check the entire inventory and containers for specific items using PartyComponent:isCarrying but this allows for a single, named item checks. I suppose it should be done with ItemComponent:hasTrait but I have no idea how to comb all champion hand slots AND inventories for item traits.

I also wanted to hudPrint progressively harsher messages informing the player that the weapons in the heroes' hands are heating up, but I'm not sure how I can integrate those with the rest of the script AND have them trigger only once.

Any help is appreciated!

Re: A thank you and a script question

Posted: Thu Apr 19, 2018 3:51 pm
by Curunir
This is the jumble of ideas I have so far. It's not complete and I have no idea if even the snppets I have are correct. Again, zero experience with code and just a few days of reading other people's work and browsing the log2doc wiki, so, apologies. What I have here is modified from other people's work and ideas.

Code: Select all

function weaponHeat()
	
	for a=1,4 do
 	for b=1,32 do
		local weaponCheck = party.party:getChampion(a):getItem(b)
		if weaponCheck:hasTrait ("light_weapon", "heavy_weapon", 
"firearm", "missile_weapon", "throwing_weapon") then
		
	damageTile(party.level, X, Y, party.facing, party.elevation, 2, "fire", damage)
	--REPEAT AS MANY TIMES AS NEEDED FOR THE NUMBER AND COORDS OF DAMAGE TILES
		
		for c=1,4 do
		if party:getChampion(c):isAlive() then
		party.party:getChampion(c):playDamageSound()
	
	hudPrint("You feel your weapons heating up to the point where they burn your skin.") 

Re: A thank you and a script question

Posted: Thu Apr 19, 2018 10:20 pm
by zimberzimber
Do you want the weapons to damage the party every few seconds, or each tile moved?

Re: A thank you and a script question

Posted: Thu Apr 19, 2018 11:08 pm
by Curunir
Ideally, standing on each tile does damage per second, first one doing 10, second doing 15, third 30 and fourth 50.

Re: A thank you and a script question

Posted: Fri Apr 20, 2018 12:10 am
by Zo Kath Ra
timer_1
- timerInterval = 1
- currentLevelOnly = true
- connected to script_entity_1.doDamage()

script_entity_1

Code: Select all

function doDamage()
	for entity in party.map:entitiesAt(party.x, party.y) do
		if (entity.script) and (entity.script.getBaseDamage) then
			local base_damage = entity.script.getBaseDamage()
			local damaged = false
			
			for i = 1, 4 do
				local champion = party.party:getChampionByOrdinal(i)
				
				if champion then
					local weapon_count = 0
					
					for j = 1, ItemSlot.MaxSlots do
						local item = champion:getItem(j)
						
						if item and (item:hasTrait("light_weapon") or item:hasTrait("heavy_weapon") or item:hasTrait("firearm") or item:hasTrait("missile_weapon") or item:hasTrait("throwing_weapon")) then
							weapon_count = weapon_count + 1
						end
					end
					
					print(champion:getName(), tostring(weapon_count))
					
					if weapon_count > 0 then
						damaged = true
						champion:damage(base_damage, "fire")
						champion:playDamageSound()
					end
				end
			end
			
			if damaged then
				hudPrint("You feel your weapons heating up to the point where they burn your skin.") 
			end
		end
	end
end
On every tile that does damage, you need a script entity with this function:

Code: Select all

function getBaseDamage()
	return 10
end
You have one script entity per tile, so each tile can have a different return value: 10, 15, 30 and 50

ItemComponent:hasTrait(trait) only accepts a single parameter, so

Code: Select all

weaponCheck:hasTrait ("light_weapon", "heavy_weapon", 
"firearm", "missile_weapon", "throwing_weapon")
does not work.
If you want, you can give every metal item in your mod the "metal" trait, by redefining these items and just adding "metal" to the traits list.
Then, you just have to check for the "metal" trait.

The script damages all champions who are carrying at least one weapon.
It doesn't matter how many weapons they're carrying, the damage is the same.
You can change this by changing the line

Code: Select all

champion:damage(base_damage, "fire")
to something like

Code: Select all

champion:damage(base_damage * weapon_count, "fire")
But then the base damage should be lower.

Re: A thank you and a script question

Posted: Fri Apr 20, 2018 12:13 am
by Curunir
Holy moly, this is a lot of code and explanation! Thank you so much for this! It's past 1am, I'm barely keeping my eyes open. I will go over this in detail tomorrow!

Thank you so much for the detailed response!

Re: A thank you and a script question

Posted: Fri Apr 20, 2018 12:44 am
by zimberzimber
A small QoL change for you as the dungeon maker that allows you to place counters instead of scripts with damage...

Code: Select all

function doDamage()
	for entity in party.map:entitiesAt(party.x, party.y) do
		-- Use this checker instead of the other one if you're going to place counters on pathable tiles related only to heating weapons
	--	if entity.counter then
		
		-- Use this checker if pathable tiles might have other counters. Must also name them ("heating_weapon_damager_"..number)
		if entity.counter and string.find(entity.name, "heating_weapon_damager") then
			local base_damage = entity.counter:getValue()
			local damaged = false
			
			for i = 1, 4 do
				local champion = party.party:getChampionByOrdinal(i)
				
				if champion then
					local weapon_count = 0
					
					for j = 1, ItemSlot.MaxSlots do
						local item = champion:getItem(j)
						
						if item and (item:hasTrait("light_weapon") or item:hasTrait("heavy_weapon") or item:hasTrait("firearm") or item:hasTrait("missile_weapon") or item:hasTrait("throwing_weapon")) then
							weapon_count = weapon_count + 1
						end
					end
					
					print(champion:getName(), tostring(weapon_count))
					
					if weapon_count > 0 then
						damaged = true
						champion:damage(base_damage, "fire")
						champion:playDamageSound()
					end
				end
			end
			
			if damaged then
				hudPrint("You feel your weapons heating up to the point where they burn your skin.") 
			end
		end
	end
end

Re: A thank you and a script question

Posted: Fri Apr 20, 2018 9:23 am
by Curunir
Again, thank you very much! I'm working my way through the script and figuring out what exactly everything does and why and it's a great learning experience!

Re: A thank you and a script question

Posted: Fri Apr 27, 2018 11:45 pm
by Curunir
Huge thank you to Skuggasveinn for the video editor tuts, to Isaac, Zo Kath Ra and Minmay for answering my questions, whether directly or through me digging through the forum, and to all the great people who contributed to this place over the years.

Two days out, working on the first map of my first mod for GR2.

https://i.imgur.com/pRATYpc.gifv mapping "timelapse" :D

https://i.imgur.com/Q27orom.jpg first proper puzzle solved