Ask a simple question, get a simple answer

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
Eburt
Posts: 69
Joined: Thu Feb 05, 2015 5:44 am

Re: Ask a simple question, get a simple answer

Post by Eburt »

minmay wrote:
THOM wrote:But if I attack this object with a torch (damageType = "fire", like the original one) it doesn't get any damage. Why is this? Other fire-damage weapons (fireburst, damageTile "fire") are doing damage... ???
Due to an implementation detail you'd rather not know about, if a HealthComponent has immunity to the "physical" damage type, it effectively becomes immune to all melee attacks, ProjectileComponent attacks (like crossbow quarrels and thrown items), and firearm attacks. TileDamagerComponent-based attacks, like fireburst, fireball, etc. will still work fine.
Here is a workaround I wrote some time ago for this issue - specifically for melee attacks. It worked for a specific case I was working on, but I haven't tested it extensively and it's been quite some time since I worked on it.
SpoilerShow

Code: Select all

defineObject{
	name = "party",
	baseObject = "party",
	components = {
		{
			class = "Party",
			
			onAttack = function(self, champion, action, slot)
				local attackType = action:getClass()
				local dx,dy = getForward(self.go.facing)
				local x = self.go.x + dx
				local y = self.go.y + dy
				
				if attackType == "MeleeAttackComponent" then
					for ent in self.go.map:entitiesAt(x,y) do
						if ent.health then
							local immunities = ent.health:getImmunities()
							local eleDmg = false
							local immune = false
							
							if immunities then
								for _,i in pairs(immunities) do
									if i == "physical" then eleDmg = true end
								end
							end
							
							if eleDmg then
								local eleType = action:getDamageType()
								for _,i in pairs(immunities) do
									if i == eleType then immune = true end
								end
								
								if immune == false then
									local baseDmgStat = action:getBaseDamageStat()
									local dmgMod = champion:getCurrentStat(baseDmgStat)
									local damage = action:getAttackPower() + dmgMod
									damageTile(self.go.level, x, y, self.go.facing, self.go.elevation, 0, eleType, damage)
								end
							end
						end
					end
				end
			end,
		},
	},
}
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

I have a Detect Undead spell that I plan to fit into my ORRR3 room, once it's complete. It's not complete yet, but it's functional; I suppose that could be adapted to detect life.

https://www.dropbox.com/s/kx60r7cvp5pgq ... d.avi?dl=0
User avatar
AndakRainor
Posts: 674
Joined: Thu Nov 20, 2014 5:18 pm

Re: Ask a simple question, get a simple answer

Post by AndakRainor »

Very interesting! You changed the material of the monster for the duration of your spell, right? I also thought about doing that for Detect Life, but I feared it would not work well for monsters with particles like the air or fire elementals. How do you want to add Detect Undead to your room only? (I had the same spell planed for the pack based on Detect Life). If it is a regular spell that champions can cast with the rune panel, may be it should be included in the pack instead?
User avatar
THOM
Posts: 1274
Joined: Wed Nov 20, 2013 11:35 pm
Location: Germany - Cologne
Contact:

Re: Ask a simple question, get a simple answer

Post by THOM »

Eburt wrote: Here is a workaround I wrote some time ago for this issue - specifically for melee attacks. It worked for a specific case I was working on, but I haven't tested it extensively and it's been quite some time since I worked on it.

mhm - doesn't work. at least this onAttack script doesn't seem to be triggered during an attack at all. If I include a simple "print" command it is not executed... :?:
THOM formaly known as tschrage
_______________________________________________
My MOD (LoG1): Castle Ringfort Thread
My MOD (LoG2): Journey To Justice Thread | Download
Eburt
Posts: 69
Joined: Thu Feb 05, 2015 5:44 am

Re: Ask a simple question, get a simple answer

Post by Eburt »

THOM wrote:
Eburt wrote: Here is a workaround I wrote some time ago for this issue - specifically for melee attacks. It worked for a specific case I was working on, but I haven't tested it extensively and it's been quite some time since I worked on it.

mhm - doesn't work. at least this onAttack script doesn't seem to be triggered during an attack at all. If I include a simple "print" command it is not executed... :?:
You may have to combine it with other modifications to the party that your mod uses. Might take a bit of searching if you're using assets others have made. Try it out in a new dungeon to make sure, but it still works fine for me...
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

Is there a way to clear any materialOverrides that were set?
User avatar
akroma222
Posts: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: Ask a simple question, get a simple answer

Post by akroma222 »

Isaac wrote:I have a Detect Undead spell that I plan to fit into my ORRR3 room, once it's complete. It's not complete yet, but it's functional; I suppose that could be adapted to detect life.

https://www.dropbox.com/s/kx60r7cvp5pgq ... d.avi?dl=0
Thats a fantastic effect for Detect life!
(ive been shining a silly red light on the monsters for a few moments :roll: )
Just in case, GoldenShadow scripted up a Detect Monster spell quite a while ago which provides text based info on monsters
viewtopic.php?f=22&t=9609&start=10
The script im currently using has changed a bit but here it is (as if you guys need scripting help lol)
SpoilerShow

Code: Select all

function detectmonster(champion, x, y, direction, elevation, skillLevel)

    local monsterNames = {air_elemental = "an Air Elemental", crab = "a Crab", crowern = "a Crowern", dark_acolyte = "a Dark Acolyte",
          eyctopus = "an Eyectopus", fire_elemental = "a Fire Elemental", fjeld_warg = "a Fjeld Warg", fjeld_warg1 = "a Fjeld Warg",
          fjeld_warg2 = "a Fjeld Warg", forest_ogre = "a Forest Ogre", giant_snake = "a giant Snake", goromorg = "a Goromorg",
          herder = "a Herder", herder_big = "a big Herder", herder_small = "a small Herder", ice_guardian = "an Ice Guardian",
          lindworm = "a Lindworm", lizard_ice = "an Ice Lizard", lizard_dark = "a Dark Lizard", lizard_fire= "a Fire Lizard",
          lizard_green = "a Green Lizard", magma_golem = "a Magma Golem", medusa = "a Medusa", mimic = "a Mimic",
          mosquito_swarm = "a Swarm of Mosquitos", mummy = "a Mummy", mummy1 = "a Mummy", mummy2 = "a Mummy", mummy3 = "a Mummy",
          ogre = "a Cave Ogre", rat_swarm = "a Swarm of Rats", ratling = "a Ratling", ratling1 = "a Ratling", ratling2 = "a Ratling",
          ratling_boss = "a Ratling Clan Chief", sand_warg = "a Sand Warg", scavenger = "a Scavenger", shrakk_torr = "a Shrakk Torr",
          skeleton_archer = "a Skeleton Archer", skeleton_commander = "a Skeleton Commander", skeleton_trooper = "a Skeleton Trooper",
          skeleton_trooper1 = "a Skeleton Trooper", skeleton_trooper2 = "a Skeleton Trooper", skeleton_warrior = "a Skeleton Warrior",
          slime_green = "a Green Slime", slime_red = "a Red Slime", slime_blue = "a Blue Slime", slime_fire = "a Fire Slime",
          slime_ice = "an Ice Slime", slime_dark = "a Dark Slime", slime_plasm = "a Plasma Slime",  slime_poison = "a Poison Slime", 
          slime_golden = "a Golden Slime", snail = "a Snail", snail_blue_green = "a Hardshell Snail", snail_green_brown = "a Deep Forest Snail",
          spider = "a Spider", spore_mushroom = "a Mushroom Sporer", summon_stone = "a Summon Stone", swamp_toad = "a Swamp Toad",
          tentacles = "a Pit Tentacle", trickster = "a Trickster", turtle = "a Turtle", turtle_diving = "a Turtle", twigroot = "a Twigroot",
          uggardian = "a Uggardian", undead = "a Zombie", viper_root = "a Viper Root", warden = "a Warden", wizard = "a Wizard", wyvern = "a Wyvern",
          xeloroid = "a Xeloroid", zarchton_diving = "a Zarchton", zarchton = "a Zarchton"}
          
	local monsterNamesplural = {air_elemental = "Air Elementals", crab = "Crabs", crowern = "Crowerns", dark_acolyte = "Dark Acolytes",
          eyctopus = "Eyectopuses", fire_elemental = "Fire Elementals", fjeld_warg = "Fjeld Wargs", fjeld_warg1 = "Fjeld Wargs",
          fjeld_warg2 = "Fjeld Wargs", forest_ogre = "Forest Ogres", giant_snake = "giant Snakes", goromorg = "Goromorgs",
          herder = "Herders", herder_big = "big Herders", herder_small = "small Herders", ice_guardian = "Ice Guardians",
          lindworm = "Lindworms", lizard_ice = "Ice Lizards", lizard_dark = "Dark Lizards", lizard_fire= "Fire Lizards",
          lizard_green = "Green Lizards", magma_golem = "Magma Golems", medusa = "Medusas", mimic = "Mimics",
          mosquito_swarm = "Swarm of Mosquitos", mummy = "Mummies", mummy1 = "Mummies", mummy2 = "Mummies", mummy3 = "Mummies",
          ogre = "Cave Ogres", rat_swarm = "Swarm of Rats", ratling = "Ratlings", ratling1 = "Ratlings", ratling2 = "Ratlings",
          ratling_boss = "Ratling Clan Chiefs", sand_warg = "Sand Wargs", scavenger = "Scavengers", shrakk_torr = "Shrakk Torrs",
          skeleton_archer = "Skeleton Archers", skeleton_commander = "Skeleton Commanders", skeleton_trooper = "Skeleton Troopers",
          skeleton_trooper1 = "Skeleton Troopers", skeleton_trooper2 = "Skeleton Troopers", skeleton_warrior = "Skeleton Warriors",
          slime_green = "Green Slimes", slime_red = "Red Slimes", slime_blue = "Blue Slimes", slime_fire = "Fire Slimes",
          slime_ice = "Ice Slimes", slime_dark = "Dark Slimes", slime_plasm = "Plasma Slimes",  slime_poison = "Poison Slimes", 
          slime_golden = "Golden Slimes", snail = "Snails", snail_blue_green = "Hardshell Snails", snail_green_brown = "Deep Forest Snails",
          spider = "Spiders", spore_mushroom = "Mushroom Sporers", summon_stone = "Summon Stones", swamp_toad = "Swamp Toads",
          tentacles = "Pit Tentacles", trickster = "Tricksters", turtle = "Turtles", turtle_diving = "Turtles", twigroot = "Twigroots",
          uggardian = "Uggardians", undead = "Zombies", viper_root = "Viper Roots", warden = "Wardens", wizard = "Wizards", wyvern = "Wyverns",
          xeloroid = "Xeloroids", zarchton_diving = "Zarchtons", zarchton = "Zarchtons"}
          
         	-------------------------------------------------------------------------------------------------------------
			local class = champion:getClass()
			local skillS = champion:getSkillLevel("staves_runewands")
		  	local skillP = champion:getSkillLevel("perception")
			local skillA = champion:getSkillLevel("accuracy")
			local aura = champion:hasTrait("aura")
			local analytic = champion:hasTrait("trained_instincts")
			local learner = champion:hasTrait("fast_learner")
			local predator = champion:hasTrait("predator")
			local precision = champion:hasTrait("deadly_precision")
			local truthSeer = champion:hasTrait("truth_seer")
			local watcher = champion:hasTrait("watcher")
			local strongMind = champion:hasTrait("watcher")
			local trapper = champion:hasTrait("watcher")
			-----------------------------------------------------------------
			local monstertotal = 0
          	local count = 1 + skillS  		--max range
          	local monsterarray = {}
          	local monsterdistance = {}
          	local maxdist = 0
          	local limit = 1 + skillP		--max targets
			-------------------------------------------------------limit bonus
			if analytic or learner or predator then
				limit = limit + 2
			end
			-------------------------------------------------------range bonus
			if strongMind or aura or trapper then
				count = count + 2
			end
			--------------------------------------
          	for fx = x - count, x + count do
             	for fy = y - count, y + count do
                	for i in party.map:entitiesAt(fx,fy) do
						------------------------------------------------ambushBoss bonus
						if precision or truthSeer or watcher then
							if i:getComponent("ambushtrigger") then
								if i:getComponent("ambushscript") then
									--delayedCall("detectScripts", 4, "detectAmbush", champion, i.go)
									print("ambushtrigger", "TODO")
									-------------------------------------ambush FX
									--addDetectLight(k.id, "detectMlight", 2.2, 1, 1, 50, 10, 0.5, 6, 8)
									----spawn("detect_monster_light", k.level, k.x, k.y, k.facing, k.elevation)
									------------------------------------
									--playSound("tech_scan_04")
									-------------------------------------
								end
								
							elseif i:getComponent("bossfight") then
								if i:getComponent("bossscript") then
									--delayedCall("detectScripts", 4, "detectBossfight", champion, i.go)
									print("bossfight", "TODO")
									-------------------------------------boss FX
									--addDetectLight(k.id, "detectMlight", 2.2, 1, 1, 50, 10, 0.5, 6, 8)
									----spawn("detect_monster_light", k.level, k.x, k.y, k.facing, k.elevation)
									------------------------------------
									--playSound("tech_scan_04")
									-------------------------------------
								end
							end
						end
						---------------------------------------------------		
                   		if i:getComponent("monster") then
						-------------------------------------------
							monstertotal = monstertotal + 1
							-------------------------------------------
                      		local xdist = (x - i.x) * 3
                      		local ydist = (y - i.y) * 3
                      		local zdist = (elevation - i.elevation) * 3
                      		local dist = math.floor(0.5 + math.sqrt(xdist^2 + ydist^2 + zdist^2))
							-------------------------------------------
                      		if i.monster:getGroupSize() > 1 then
                         		if monstertotal > 1 
								and i.x == monsterarray[monstertotal - 1].x 
								and i.y == monsterarray[monstertotal - 1].y 
								and i.elevation == monsterarray[monstertotal - 1].elevation then
                            		monstertotal = monstertotal - 1
                         		else
                            		monsterdistance[i] = dist
                         		end
                      		else
	                         	monsterdistance[i] = dist
                      		end
							--------------------------------------------
                      		if dist > maxdist then
                         		maxdist = dist
                      		end
                      		monsterarray[monstertotal] = i
							--------------------------------------------																				
                   		end
               	 	end
             	end
          	end
          	--------------------------------------------
			local skillcount = 0
			--------------------------------------------
			for m = 0, maxdist do
             	for k,v in pairs(monsterdistance) do
					--------------------------------------------
                	if m == v and skillcount < limit then
						--------------------------------------------
                   		local deltax = x - k.x
                   		local deltay = y - k.y
                   		local mdir = 0
                   		local height = ""
						--------------------------------------------
                   		if math.abs(deltax) <= math.abs(deltay) then
                      		if deltay == 0 then
                         		mdir = -1
                      		elseif deltay > 0 then
                         		mdir = (4 + direction) % 4
                      		else
                         		mdir = (6 + direction) % 4
                      		end
                   		else
                      		if deltax == 0 then
                         		mdir = -1
                      		elseif deltax > 0 then
                         		mdir = (5 + direction) % 4
                      		else
                         		mdir = (7 + direction) % 4
                      		end
                   		end
						--------------------------------------------
                   		if elevation == k.elevation then
                      		height = ""
                   		elseif elevation < k.elevation then
                      		height = ", above you"
                   		else
                      		height = ", below you"
                   		end
						-------------------------------------------------------------------------Staff def, trained Inst
                   		local fdir = ""
						--------------------------------------------nameGroupElevation bonus
						if class == "ranger" or class == "ninja" 
						or class == "illusionist" or class == "rogue" then
                   			if mdir == -1 then
                      			fdir = height
                   			elseif mdir == 0 then
                      			fdir = ""..height..", in front of the party"
                   			elseif mdir == 1 then
                      			fdir = ""..height..", to the left of the party"
                   			elseif mdir == 2 then
                      			fdir = ""..height..", behind the party"
                   			elseif mdir == 3 then
                      			fdir = ""..height..", to the right of the party"
                   			end
						end
                   		--------------------------------------------
						skillcount = skillcount + 1
						------------------------------------------------------------------------
						--addDetectLight(k.id, "detectMlight", 2.2, 1, 1, 50, 10, 0.5, 6, 8)
						--spawn("detect_monster_light", k.level, k.x, k.y, k.facing, k.elevation)
						------------------------------------
						--playSound("tech_scan_04")
						-----------------------------------------------------------------------
                   		if k.monster:getGroupSize() <= 1 then
							--------------------------------------------nameGroupElevation bonus
							if class == "ranger" or class == "ninja" 
							or class == "illusionist" or class == "rogue" then
								hudPrint("There is "..monsterNames[k.name].." "..m.." meters away"..fdir..".")
							else	
								hudPrint("There is an enemy "..m.." meters away"..fdir..".")	
							end
							--------------------------------------------
                   		else
							--------------------------------------------nameGroupElevation bonus
							if class == "ranger" or class == "ninja" 
							or class == "illusionist" or class == "rogue" then
								hudPrint("There is a group of "..k.monster:getGroupSize().." "..monsterNamesplural[k.name].." "..m.." meters away"..fdir..".")
							else	
                      			hudPrint("There is a group of enemies "..m.." meters away"..fdir..".")	
                   			end 						
						end
                	end
            	end
          	end
       	end
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

AndakRainor wrote:Very interesting! You changed the material of the monster for the duration of your spell, right? I also thought about doing that for Detect Life, but I feared it would not work well for monsters with particles like the air or fire elementals. How do you want to add Detect Undead to your room only? (I had the same spell planed for the pack based on Detect Life). If it is a regular spell that champions can cast with the rune panel, may be it should be included in the pack instead?
I haven't decided if the spell will be cast-able, or if it will require item usage to cast. It is one of a few spells meant to be Boss-loot.
User avatar
THOM
Posts: 1274
Joined: Wed Nov 20, 2013 11:35 pm
Location: Germany - Cologne
Contact:

Re: Ask a simple question, get a simple answer

Post by THOM »

Eburt wrote:
THOM wrote:
Eburt wrote: Here is a workaround I wrote some time ago for this issue - specifically for melee attacks. It worked for a specific case I was working on, but I haven't tested it extensively and it's been quite some time since I worked on it.
mhm - doesn't work. at least this onAttack script doesn't seem to be triggered during an attack at all. If I include a simple "print" command it is not executed... :?:
You may have to combine it with other modifications to the party that your mod uses. Might take a bit of searching if you're using assets others have made. Try it out in a new dungeon to make sure, but it still works fine for me...
Mmh. You are right - your script works in a brand new dungeon. But still not in mine.

I've erased all additions I made to the party-object - no result. What could break an party-onAttack action in my mod? Items that uses the onAttack hook, too?
THOM formaly known as tschrage
_______________________________________________
My MOD (LoG1): Castle Ringfort Thread
My MOD (LoG2): Journey To Justice Thread | Download
Eburt
Posts: 69
Joined: Thu Feb 05, 2015 5:44 am

Re: Ask a simple question, get a simple answer

Post by Eburt »

No, the two hooks are definitely called separately - I was specifically taking advantage of that in my dungeon. Even if you return false from the weapon onAttack() hook the party onAttack() is still called (though my script won't do anything meaningful without an attack of course).

I'm not really sure what could be causing it. Maybe start adding your custom assets to a new dungeon and test until it breaks? Or easier might be to back-up your dungeon, delete everything from the copy and then begin commenting out the import scripts until it starts working again?

Only other thing I can think of is that onAttack() doesn't get called for bare-hand attacks, but I assume that's not your issue.
Post Reply